My favorites | Sign in
Project Logo
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//Cg

/*
We were using setShaderInput in the Python code. setShaderInput does nothing
more than assign a float4 (there is no possibility to assign a float2 e.g.) to a
shader uniform. Every manually provided input needs a k_ prefix therefore the
panda3drocks shader input has to be written as k_panda3drocks. If you manually
define an uniform in shader, you must at least call setShaderInput on an
appropriate NodePath that uses this shader.
*/
void vshader(
uniform float4x4 mat_modelproj,
uniform float4 k_panda3drocks,
in float4 vtx_position : POSITION,
out float4 l_my : TEXCOORD0,
out float4 l_position : POSITION)
{
l_position = mul(mat_modelproj, vtx_position);
l_my = k_panda3drocks;
}

/*
This example is a bad idead how to waste a TEXCOORD unit. k_panda3drocks is a
constant assigned to l_my, when l_my it is passed from the vertex shader to
fragment shader it is lineraly interpolated. But a linear interpolated constant,
is a constant. In this sample, it would make more sense if we define our uniform
in the fragment shader than in the vertex shader.
*/
void fshader(
in float4 l_my : TEXCOORD0,
out float4 o_color : COLOR)
{
o_color = l_my;
}

/*
I have to admit here an unknowingness. GLSL does interpolate perspectively
correct (based on the depth the linear interpolation gets a correction), but I
do not know in which circumstances this applies to Cg. It may be possible that I
repeat the word linearly interpolated over and over again although it is not
always exactly true. Both the GLSL manual and the Cg manual only have the word
perspectively correction on one line, there is no explanation. If anyone has in
depth information about this I am happy if you share this knowledge.

Both GLSL and Cg support a keyword noproject to disable this correction. But
Panda3D currently does not support it.

http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf
http://developer.download.nvidia.com/cg/Cg_2.0/2.0.0015/Cg-2.0_May2008_ReferenceManual.pdf

The OpenGL function glHint has a parameter to enable or disable perspective
correction (GL_PERSPECTIVE_CORRECTION_HINT), but maybe that only applies to the
fixed function pipeline.

http://www.opengl.org/sdk/docs/man/xhtml/glHint.xml

As of OpenGL 2.1 perspective correction should always be enabled according to
the manual.

I bet that it depends on the GPU vendors daily mood, the moon phase and the
Google result to: "number of horns on a unicorn multiplied by the answer to
life, the universe and everything".
*/

/*
However I like to explain why we need perspective correction. A scan line
renderer like today GPUs are (in contrast to a ray tracer), transforms all three
points of a triangle from 3D space to a 2D screen. After the transformation e.g.
the linear interpolation of colors is calculated. Only if we transform a
triangle to our screen we know how much pixels the triangle will cover. If we
like to interpolate in 3D we may interpolate millions of position that are
reduced to one pixel if the triangle is far away, this is obviously infeasible.
Open the figures.svg of figures.png file and look at the figure 5.1. If you look
at the first image you can see a quad that consists of two triangles. You can
look at this image from two view points. First it is possible that is a
perspective plane in 3D, second it is a trapezoid in 2D. There are two yellow
lines in the image. This lines divide the trapezoid exactly in the center. Maybe
you already see a problem, this is only true in 2D. In 3D the center of the
trapezoid is a bit above the current center. Further on there are five marked
intersections. We need this numbers for the later images:

1: Exact 2D center for the top line.
2: Exact 2D center for the left line.
3: Exact 2D center for the right line.
4: Exact 2D center for the bottom line.
5: Exact 2D center for the line in the middle.

Now we start with the second image and assign some colors to the vertices. We
now interpolate this values manually at the intersection points:

1: 50% red 50% blue.
2: 100% red 0% blue.
3: 50% red 50% blue.
4: 0% red 100% blue.
5: 50% red 50% blue.

While 1 2 3 and 4 should be easy to calculate maybe 5 is not so obvious. But
because we now that the point is exactly at center between the top right vertex
and the bottom left vertex, the color must be the center between red and blue as
well.

In the third image you can see how this should look like. It looks nice, but it
is not correct, because the average of blue and red (50% red and 50% blue) lies
exactly in the center of the trapezoid and not in the center of the 3D plane we
have. The gradient looks nice because all colors on one horizontal have one and
the same color (point 1, 3 and 5 have the same color e.g.).

In the fourth image we rotate our plane. The only thing that changes are the
vertex colors. The interpolated colors are as follows this time:

1: 0% red 100% blue.
2: 50% red 50% blue.
3: 100% red 0% blue.
4: 50% red 50% blue.
5: 50% red 50% blue.

Point 5 has the same color as in the previous image. Because we have another
gradient now, all vertical lines should have the exact same color, but this is
not true. Point 2, 4 and 5 have the same color, but they are not on the same
line.

In the fifth image you can see the final result. Maybe it is not that obvious
but the green line, tries to show how the 50% line looks like.

You can reproduce this problem if you draw a rectangle yourself in a 3D
application and apply the perspective transformation on the vertices by
yourself. The rectangle looks like a trapezoid then. If you draw a trapezoid in
Blender e.g. and assign a texture with the following UV coordinates (of a grid
like image) to the four vertices: (0,0) (1,0) (0,1) (1,1) you can see the
distortion more clearly. The two files perspective-correction.blend and
perspective-correction.jpg show you the result more clearly. You can see one
more fancy thing with this example. The preview in Blender is renderer with
OpenGL while the Blender itself has its own renderer for production quality
images. The internal renderer and OpenGL divide a quad in two different ways
into triangles. That is the reason why the vertical line on the trapezoid does
is twisted in two different directions.

Conclusion: The linear interpolation needs a correction factor (based on the Z
buffer), so final images are not distorted in an unnatural way.
*/
Show details Hide details

Change log

r39 by Azraiyl on May 22, 2009   Diff
Minor typos.
Go to: 
Project members, sign in to write a code review

Older revisions

r28 by azraiyl on Oct 13, 2008   Diff
Some final notes about perspective
correction.
r25 by azraiyl on Oct 12, 2008   Diff
Typos fixed.
r24 by azraiyl on Oct 10, 2008   Diff
Minor typo.
All revisions of this file

File info

Size: 6573 bytes, 140 lines
Hosted by Google Code