Saturday, January 7, 2012

Deferred Shading by OpenGL

It is quite popular to use deferred shading and not standard shading these days. A lot of the details already described well with pros and cons.
With many lights and vertices - worth to check and I have seen already 5.8x better results for deferred approach: Def: 480FPS vs Std: 84FPS for 1081344 vertices
Based on the model(s): Harley Quinn contains a bit more than 36K vertices alone.
Where from the OpenGL side, differences are (Left is deferred shading): ExamDiff Pro Diff Report
First Text Fragment
Second Text Fragment
1 //Pass 1
2 //Draw the geometry, saving parameters into the buffer
3
4 //Make the pbuffer the current context
5 pbuffer.MakeCurrent();
6
7 //Clear buffers
8 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
10
11 glLoadIdentity();
12 gluLookAt( 0.0f, 4.0f, 3.0f,
13 0.0f, 0.0f, 0.0f,
14 0.0f, 1.0f, 0.0f);
15
16 //Bind and enable vertex & fragment programs
17 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, deferredShadingPass1VP);
18 glEnable(GL_VERTEX_PROGRAM_ARB);
19
20 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, deferredShadingPass1FP);
21 glEnable(GL_FRAGMENT_PROGRAM_NV);
22
23 //Draw the torus knot
24 glDrawElements(GL_TRIANGLES, torusKnot.numIndices, GL_UNSIGNED_INT, (char *)NULL);
25
26 //Draw the "floor"
27 glNormal3f(0.0f, 1.0f, 0.0f);
28 glBegin(GL_TRIANGLE_STRIP);
29 {
30 glVertex3f( 5.0f,-0.5f, 5.0f);
31 glVertex3f( 5.0f,-0.5f,-5.0f);
32 glVertex3f(-5.0f,-0.5f, 5.0f);
33 glVertex3f(-5.0f,-0.5f,-5.0f);
34 }
35 glEnd();
36
37 glDisable(GL_VERTEX_PROGRAM_ARB);
38 glDisable(GL_FRAGMENT_PROGRAM_NV);
39
40 //Copy the pbuffer contents into the pbuffer texture
41 glBindTexture(GL_TEXTURE_RECTANGLE_NV, pbufferTexture);
42 glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, 0, 0,
43 pbuffer.width, pbuffer.height);
44
45 //Make the window the current context
46 WINDOW::Instance()->MakeCurrent();
47
48 //Pass 2
49 //Draw a quad covering the region of influence of each light
50 //Unpack the data from the buffer, perform the lighting equation and update
51 //the framebuffer
52
53 //Set orthographic projection, 1 unit=1 pixel
54 glMatrixMode(GL_PROJECTION);
55 glPushMatrix();
56 glLoadIdentity();
57 gluOrtho2D(0, WINDOW::Instance()->width, 0, WINDOW::Instance()->height);
58
59 //Set identity modelview
60 glMatrixMode(GL_MODELVIEW);
61 glPushMatrix();
62 glLoadIdentity();
63
64 //Disable depth test
65 glDisable(GL_DEPTH_TEST);
66
67 //Bind the pbuffer texture
68 glBindTexture(GL_TEXTURE_RECTANGLE_NV, pbufferTexture);
69
70 //Bind and enable fragment program
71 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, deferredShadingPass2FP);
72 glEnable(GL_FRAGMENT_PROGRAM_NV);
73
74 //Loop through the lights
75 for(int i=0; i<numLights; i)
76 {
77 //Calculate the rectangle to draw for this light
78 int rectX, rectY, rectWidth, rectHeight;
79
80 lights[i].GetWindowRect(WINDOW::Instance()->width, WINDOW::Instance()->height,
81 viewMatrix, currentTime, cameraNearDistance,
82 cameraFovy, cameraAspectRatio,
83 rectX, rectY, rectWidth, rectHeight);
84
85 //Enable additive blend if i>0
86 if(i>0)
87 {
88 glBlendFunc(GL_ONE, GL_ONE);
89 glEnable(GL_BLEND);
90 }
91
92 //Send the light's color to fragment program local parameter 0
93 glProgramLocalParameter4fvARB( GL_FRAGMENT_PROGRAM_NV, 0, lights[i].color);
94
95 //Send 1/(light radius)^2 to fragment program local parameter 1
96 float inverseSquareLightRadius=1.0f/(lights[i].radius*lights[i].radius);
97 glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_NV, 1,
98 inverseSquareLightRadius, inverseSquareLightRadius,
99 inverseSquareLightRadius, inverseSquareLightRadius);
100
101 //Send the light's position to fragment program local parameter 2
102 glProgramLocalParameter4fvARB( GL_FRAGMENT_PROGRAM_NV, 2,
103 VECTOR4D(lights[i].GetPosition(currentTime)));
104
105 //Draw the rectangle
106 glBegin(GL_TRIANGLE_STRIP);
107 {
108 glVertex2i(rectX, rectY);
109 glVertex2i(rectX rectWidth, rectY);
110 glVertex2i(rectX, rectY rectHeight);
111 glVertex2i(rectX rectWidth, rectY rectHeight);
112 }
113 glEnd();
114 }
115
116 //Restore matrices
117 glMatrixMode(GL_PROJECTION);
118 glPopMatrix();
119 glMatrixMode(GL_MODELVIEW);
120 glPopMatrix();
121
122 glEnable(GL_DEPTH_TEST);
123 glDisable(GL_FRAGMENT_PROGRAM_NV);
124 glDisable(GL_BLEND);
125
1 //Make an initial pass to lay down Z
2 glColorMask(0, 0, 0, 0);
3
4 //Draw the torus knot
5 glDrawElements(GL_TRIANGLES, torusKnot.numIndices, GL_UNSIGNED_INT, (char *)NULL);
6
7 //Draw the "floor"
8 glNormal3f(0.0f, 1.0f, 0.0f);
9 glBegin(GL_TRIANGLE_STRIP);
10 {
11 glVertex3f( 5.0f,-0.5f, 5.0f);
12 glVertex3f( 5.0f,-0.5f,-5.0f);
13 glVertex3f(-5.0f,-0.5f, 5.0f);
14 glVertex3f(-5.0f,-0.5f,-5.0f);
15 }
16 glEnd();
17
18 glColorMask(1, 1, 1, 1);
19
20 //Bind and enable vertex & fragment programs
21 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, standardShadingVP);
22 glEnable(GL_VERTEX_PROGRAM_ARB);
23
24 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, standardShadingFP);
25 glEnable(GL_FRAGMENT_PROGRAM_ARB);
26
27 //Loop through the lights
28 for(int i=0; i<numLights; i)
29 {
30 //Calculate and set the scissor rectangle for this light
31 int scissorX, scissorY, scissorWidth, scissorHeight;
32
33 lights[i].GetWindowRect(WINDOW::Instance()->width, WINDOW::Instance()->height,
34 viewMatrix, currentTime, cameraNearDistance,
35 cameraFovy, cameraAspectRatio,
36 scissorX, scissorY, scissorWidth, scissorHeight);
37
38 glScissor(scissorX, scissorY, scissorWidth, scissorHeight);
39 glEnable(GL_SCISSOR_TEST);
40
41 //Enable additive blend if i>0
42 if(i>0)
43 {
44 glBlendFunc(GL_ONE, GL_ONE);
45 glEnable(GL_BLEND);
46 }
47
48 //Calculate the object space light position and send to
49 //vertex program local parameter 0
50 //Object space and world space are the same
51 glProgramLocalParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 0,
52 VECTOR4D(lights[i].GetPosition(currentTime)));
53
54 //Send the light's color to fragment program local parameter 0
55 glProgramLocalParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 0, lights[i].color);
56
57 //Send 1/(light radius)^2 to fragment program local parameter 1
58 float inverseSquareLightRadius=1.0f/(lights[i].radius*lights[i].radius);
59 glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 1,
60 inverseSquareLightRadius, inverseSquareLightRadius,
61 inverseSquareLightRadius, inverseSquareLightRadius);
62
63 //Draw the torus knot
64 glDrawElements(GL_TRIANGLES, torusKnot.numIndices, GL_UNSIGNED_INT, (char *)NULL);
65
66 //Draw the "floor"
67 glNormal3f(0.0f, 1.0f, 0.0f);
68 glBegin(GL_TRIANGLE_STRIP);
69 {
70 glVertex3f( 5.0f,-0.5f, 5.0f);
71 glVertex3f( 5.0f,-0.5f,-5.0f);
72 glVertex3f(-5.0f,-0.5f, 5.0f);
73 glVertex3f(-5.0f,-0.5f,-5.0f);
74 }
75 glEnd();
76 }
77
78 glDisable(GL_VERTEX_PROGRAM_ARB);
79 glDisable(GL_FRAGMENT_PROGRAM_ARB);
80 glDisable(GL_SCISSOR_TEST);
81 glDisable(GL_BLEND);
Number of differences: 10
Added(5,22)
Deleted(0,48)
Changed(82)
Changed in changed(42)
Ignored

Shaders side will be later...

PS have you seen a good difference viewer ?

No comments:

Post a Comment