Programmable Graphics pipeline / Hardware based graphics ...

rodscarletSoftware and s/w Development

Dec 14, 2013 (3 years and 5 months ago)

150 views

Programmable Shaders

Graphics programmable functions
pipeline

suriyong L.

1

Introduction


In this past few years, graphics processors
have changed dramatically.


Former rendering was used fixed process
box of pipeline


The rendering is now not fixed, it contained
vertex shader and fragment shader.


In recently year OpenGL pipeline was
supported by most hardware

suriyong L.

2

OpenGL fixed function pipelines


Conventional OpenGL pipeline






The state can be changed by user

Vertex
processor

Clipping and
primitive assembly

Rasterizer

Fragment
processor

Vertices

Object
Coordinates

Clip
Coordinates

Normalized device
Coordinates

Window
Coordinates

Pixels

suriyong L.

3

Programmable function pipeline


Use
OpenGL
Shading
Language (GLSL)


C like language for shading object


It’s divided into 2 shaders


Vertex shader

: deal with vertices and it’s attribute


Fragment shader (Pixel shader) deal with pixel or object fragment

suriyong L.

4

Programmable function pipeline

suriyong L.

5

Vertex and fragment processor process


suriyong L.

6

Vertex processor


Input


Vertices


Vertex attributes
eg
.


normal, color, texture etc., lighting, materials


Passed through via internal variable
eg
.
gl_Vertex


Processing


Convert from WCS to ECS


Mostly use
gl_ProjectionModelViewMatrix
*
gl_Vertex


Output


Position or object in ECS through
gl_Position


suriyong L.

7

Fragment Processor


Input


vectors and position from vertex processor


Pass through via
gl_Position

etc.


Process


Create color fragment of object


Output


Object fragmented color


Pass through
gl_FragColor

etc.

suriyong L.

8

Simple complete shader programs

/* pass through vertex shader */

void main(void)
{


gl_Position

=
gl_ProjectionMatrix
*
gl_ModelViewMatrix
*
gl_Vertex
;

}


// pass through fragment shader

void main() {

gl_FragColor

=
gl_FrontColor
;

}

suriyong L.

9

Setting a project


There are 2 parts needed


OpenGL API


GLSL

suriyong L.

10

OpenGL API


Create program as usual


But need

to interface to OpenGL Extension (OpenGL >
2.0)


Required header
glew.h

in OpenGL API


#include <
gl
/
glew.h
> // above
glut.h


#include <
gl
/
glut.h
> //standard OpenGL header


Inclusion files


OpenGL Extension Wrangler (GLEW)


include file
-

glew.h


lib file


glew.lib


dll

file


glew.dll


Each file should be placed in its standard location like
glut


suriyong L.

11

OpenGL API con.


First
init

the
glew

glewInit
();


Check for the OpenGL Extension Version


Set Shaders


vertex shader, fragment shader, program


compile


link to program


Set to current pipeline


glUseProgram
(program)

suriyong L.

12

Linking with GLSL functions process diagram

Note: I create a class called shader “shader.cpp” and “
shader.h
” for
this utility

suriyong L.

13

GLSL part


Create vertex and fragment source code by
text editor


They are C
-
like program

suriyong L.

14

GLSL fundamental

suriyong L.

15

Data types and qualifiers


Standard c data type
eg
.
int
, float, unsigned.
etc


No double, pointer


Extension data type


vec2, vec3, vec4 // floating point vector


ivec2, ivec3, ivec4 //
interger

vector


mat2, mat3, mat4 // floating point only


sampler

// texture representation


Qualifiers


A keyword that set the variable duty


uniform : variable not change in shader but modified in OpenGL side


varying : variable can change in both shaders


in : that argument is an input argument


out,
inout

etc.

suriyong L.

16

Swizzling

property


Sometime the structure type is used in a different meaning
eg
.

vec4
pos
; //as
location,its

members are
x,y,z

and w


If it is used in the color meaning

vec4 color; //as color, its members can be
r,g,b

and a


Both of them must have a known member type


Another meaning of swizzle


Its member can reorder or able to access multiple members at a time
eg
.

vec4
pos
; // 4 members vector

pos.x

// member x

pos.xy

// member x and y return vec2 type

pos.wzyx

// member with reverse order

pos.xxyy

// member with only 2 repeat components


But this cannot !!!

pos.ryz

// the
compoent

is not in the same group

suriyong L.

17

Built


in variable, qualifier, and data type


New data type


vec2, vec3, vec4


mat


Built in qualifier


attribute, uniform, varying


Built in variables


need not to be declared in shader


begin with “
gl
_”


gl_Vertex
,
gl_FrontColor

suriyong L.

18

Attribute qualifier


Used in vertex shader


Variable can change at most once per vertex shader


The built
-
in variable


gl_Vertex
,
gl_FrontColor

are attribute
qulifier

variable


Only floating point types can be attribute qualified.


attribute float temperature;


attribute vec3 velocity;

suriyong L.

19

Uniform qualifier


Set the variable value uniform entire the
primitive


The value is assigned outside the scope of
glBegin
() and
glEnd
();


Its mechanism is
proviede

for sharing data
among OpenGL API and shaders.

suriyong L.

20

Passing value OpenGL

GLSL



Via uniform variable


Step in OpenGL API


Get variable position use
glGetUniformLocation

int

Loc

=
glGetUniformLocation
(“name”);

“name” : variable name string


Set variable value use
glUniform

eg
. for vector variable

glUniform3f(
Loc
, 1, 2, 3);


Read the variable value via
glGetUniform

glGetUniformfv
(program, location,
variable_string
);

ex.

glGetUniformfv
(brick,
Loc
, “
brickval
”);

// read a GLSL variable name
brickval

suriyong L.

21

Varying qualifier


Role the providing data conveyed from
vertex shader to fragment shader


The variable are defined on per vertex basis


gl_FrontColor

suriyong L.

22

Fragment Shader


The same syntax as vertex programs but execute after rasterizer.


operate on each fragment


A minimal fragment shader program

/* simple fragment program */

void main() {


gl_FragColor

=
gl_FrontColor
;

}


The difference of
gl_FrontColor

have been produced by interpolating the
vertex value

suriyong L.

23

GLSL lacks of pointer


a mechanism known as call by value
-
return
is used


parameter need in, out , inout qualifier


variable like array cannot directly transfer

suriyong L.

24

Operator


use operator overloading like for some quantity
eg
.

mat4 a;

vec4 b, c, d;

c = b*a;

// make sense but result is row
vector

d = a*b;

// make sense but result is column
vector


This operator type called
swizzling

operator

suriyong L.

25

Built
-
in variable


prefixed with “
gl
_”
eg
.
gl_Vertex
, …


cannot use as an identifier


Importance:


gl_Vertex

// vertices from OpenGL


gl_ProjectionModelViewMatrix

// transform matrix


gl_Position

//
out put

from vertex shader


gl_FragColor

// output from fragment shader

suriyong L.

26

Built
-
in function


Importance

ftransform
() ; // a generally OpenGL transform

abs(); // return and absolute value


etc.

suriyong L.

27

Program examples

suriyong L.

28

Point Light
Phong

shading

//vertex shader

void
main (void) {


vec3
transformedNormal
;


float
alphaFade

= 1.0;


// Eye
-
coordinate position of vertex, needed in various calculations


vec4
ecPosition

=
gl_ModelViewMatrix

*
gl_Vertex
;


gl_Position

=
ftransform
();


transformedNormal

= normalize(
gl_NormalMatrix

*
gl_Normal
);


flight(
transformedNormal
,
ecPosition
,
alphaFade
);

}

void flight(in vec3 normal, in vec4
ecPosition
, float
alphaFade
) {


vec3 ecPosition3 = (vec3 (
ecPosition
)) /
ecPosition.w
;


vec3
eye

= vec3 (0.0, 0.0, 1.0);



vec4 Ambient = vec4 (0.0);


vec4 Diffuse = vec4 (0.0);


vec4 Specular = vec4 (0.0);

pointLight
(normal, eye, ecPosition3, Ambient, Diffuse, Specular);

vec4 color =
gl_FrontLightModelProduct.sceneColor

+
Ambient*
gl_FrontMaterial.ambient

+ Diffuse
*
gl_FrontMaterial.diffuse
;


color += Specular *
gl_FrontMaterial.specular
;


color = clamp( color, 0.0, 1.0 );

gl_FrontColor

= color;

gl_FrontColor.a

*=
alphaFade
;

}


suriyong L.

29

void
pointLight
(in vec3 normal, in vec3 eye, in vec3 ecPosition3,
inout

vec4 ambient,
inout

vec4 diffuse
,
inout

vec4 specular
) {


vec3
VP
=
normalize(vec3(
gl_LightSource
[0
].position)
-

ecPosition3);
// incidence
vec


float d = length(VP); //
its distance


float
attenuation =
1.0/(
gl_LightSource
[0].
constantAttenuation

+
gl_LightSource
[0].
linearAttenuation
*d
+
gl_LightSource
[0
].
quadraticAttenuation
*d*d);


vec3
halfVector

= normalize(VP + eye);


float
nDotVP

= max(0.0, dot(normal, VP));


float
nDotHV

= max(0.0, dot(normal,
halfVector
));


float
pf

= (
nDotVP
==0.0)? 0.0:pow(
nDotHV
,
glFrontMaterial.shininess
;


ambient +=
gl_LightSource
[
i
].ambient * attenuation;


diffuse +=
gl_LightSource
[i].diffuse *
nDotVP

*
attenuation
;


specular +=
gl_LightSource
[
i
].specular *
pf

* attenuation;

}




// Fragment shader


void main() {


vec4 color;



color =
gl_Color
;


gl_FragColor

= color;

}


suriyong L.

30

//
Opengl

Main program

#
include <
stdlib.h
>

#include <GL/
glew.h
>

#include <GL/
glut.h
>

#include "
shader.h



int

main(
int

argc
, char **
argv
) {

glutInitDisplayMode
(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

glutInitWindowSize
(
window_width
,
window_height
);

glutInitWindowPosition
(500,100);

glutCreateWindow
("Hardware Shader sphere demo");

int

gl_major
,
gl_minor
;

glewInit
();

getGlVersion
(&
gl_major
, &
gl_minor
);

printf
("GL_VERSION %
d.%d
\
n",
gl_major
,
gl_minor
);


if (
gl_major

< 2) {
printf
("Require OpenGL 2.0 or greater...exiting
\
n"); exit(1); }

phong

= Shader("
phongPoint
");

glEnable
(GL_DEPTH_TEST); /* Enable hidden
--
surface
--
removal */


glShadeModel
(GL_SMOOTH); /*enable smooth shading */


glEnable
(GL_DEPTH_TEST); /* enable z buffer */


glClearColor

(0.0, 0.0, 0.0, 0.0);glColor3f (1.0, 0.0, 0.0);

gluPerspective
(45,
window_width
/
window_height
, 2, 9);
glutReshapeFunc
(
myReshape
);

glutDisplayFunc
(display);
glutIdleFunc
(idle);


glutMainLoop
();

return 0;

}

suriyong L.

31

float
window_width

= 300,
window_height

= 300, viewer[] ={0,0,5}, theta = 0.0;

Shader
phong
;

void display(void) {

glClear
(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode
(GL_MODELVIEW);
glLoadIdentity
();

gluLookAt
(viewer[0],viewer[1],viewer[2], 0,0,0, 0,1,0);

glUseProgram
(
phong.programObject
);

glRotatef
(theta, 0,0,1);

glutSolidSphere
(1.0,20, 20);

glFlush
();
glutSwapBuffers
();

}

void
myReshape
(
int

w,
int

h) {


glViewport
(0, 0, w, h);
window_width

= w;
window_height

= h;


glMatrixMode
(GL_PROJECTION);
glLoadIdentity
();

gluPerspective
(45,
window_width
/
window_height
, 2, 9);

glutPostRedisplay
();

}

void idle() { theta += 0.01;
glutPostRedisplay
(); }

void
getGlVersion
(
int

*major,
int

*minor ){


const

char*
verstr

= (
const

char*)
glGetString
( GL_VERSION );


if((
verstr

== NULL) || (
sscanf
(
verstr
, "%
d.%d
", major, minor ) != 2) ) {


*major = *minor = 0;
fprintf
(
stderr
, "Invalid GL_VERSION format!!!
\
n" );


}

}


suriyong L.

32

References


LightHouse3D, GLSL tutorial


Edward Angle,
Interactive Computer Graphics, a
Topdown

approach
using OpenGL 4
th

edition
, Addison Wesley.


OpenGL.org, GLSL 2.1 spec.


OpenGL the orange book

suriyong L.

33