My favorites
|
Sign in
p3dst
Panda3D Shader Tutorials
Project Home
Source
Checkout
|
Browse
|
Changes
|
r46
Source path:
svn
/
trunk
/
0.py
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
"""
This is a basic example without any shader. If you do not understand a line,
please have a look at the Panda3D manual, there is not a single bit of magic in
this file.
"""
import sys
import direct.directbase.DirectStart
from direct.interval.LerpInterval import LerpFunc
from pandac.PandaModules import Texture, TextureStage
base.setBackgroundColor(0.0, 0.0, 0.0)
base.disableMouse()
base.camLens.setNearFar(1.0, 50.0)
base.camLens.setFov(45.0)
camera.setPos(0.0, -20.0, 10.0)
camera.lookAt(0.0, 0.0, 0.0)
root = render.attachNewNode("Root")
root.setPos(0.0, 0.0, 0.0)
textureArrow = loader.loadTexture("arrow.png")
textureArrow.setWrapU(Texture.WMClamp)
textureArrow.setWrapV(Texture.WMClamp)
stageArrow = TextureStage("Arrow")
stageArrow.setSort(1)
textureCircle = loader.loadTexture("circle.png")
textureCircle.setWrapU(Texture.WMClamp)
textureCircle.setWrapV(Texture.WMClamp)
stageCircle = TextureStage("Circle")
stageCircle.setSort(2)
"""
Please open the file cube.egg with a text editor. Egg files are human
readable. We will need this information later on to understand how the
vertex shader and the fragment shader works. You can also see how the
model looks like in panda by using the pview model viewer.
The cube has six faces. Each face has four different vertices. Therefore
this cube has 24 vertices. Theoretically a cube only needs eight
vertices with each vertex being shared by three faces. The problem with
this is that each vertex can only have one color, but what happens if
we want each of the six faces to be a different color? This is impossible
if the cube is only defined with eight vertices. There are more
disadvantages if we only define the cube with eight vertices, which we
will talk about later on. The only advantage of having less vertices is
that we have to send less vertices to the graphic card but in almost all
applications vertices are not a limiting factor. The memory consumption
of vertices in comparison to the memory consumption of textures is
negligible. Besides the color entry for a vertex, a vertex also has one
UV entry associated with it.
It may be useful if you modify the vertices manually and see the results.
// A vertex entry in an egg file
...
<Vertex> 0 {
1.0 1.0 -1.0 // The vertex position
<UV> { 1.0 1.0 } // The vertex UV
<RGBA> { 1.0 0.0 0.0 1.0 } // The vertex color in RGBA format
}
...
"""
modelCube = loader.loadModel("cube.egg")
"""
Next look at the colors defined in the egg file. If you compare all the
color entries, you will only find eight unique colors in the egg file.
Why does the model have thousands of colors when viewed in the model
viewer then? This is because of linear interpolation, where a value is
generated between two different values based on a "distance". Today
graphic cards are very good at linear interpolation with the ability to
do billions of linear interpolations per second. The downside is that
sometimes the graphic card can ONLY do linear interpolation and you can't
change that, even with a shader.
Back to the colors. If you have a red color (1.0, 0.0, 0.0) on one vertex
and a dark blue color (0.0, 0.0, 0.5) on the other vertex the graphic
card simply interpolates the color for every pixel between this two
vertices, even without shaders (only if requested, but Panda3D ask the
graphic card to do this). The graphic card doesn't know that a color
comes in three parts: Red, Green and Blue. It only knows that it is
manipulating values, in this case adjusting the constituent values for
Red Green and Blue. Here is an example of how the graphic card interpolates:
100% at red vertex, 0% at dark blue vertex => 1.0, 0.0, 0.0
75% at red vertex, 25% at dark blue vertex => 0.75, 0.0, 0.125
50% at red vertex, 50% at dark blue vertex => 0.5, 0.0, 0.25
25% at red vertex, 75% at dark blue vertex => 0.25, 0.0, 0.375
0% at red vertex, 100% at dark blue vertex => 0.0, 0.0, 0.5
A simplified version of how the graphic card draws the model (in reality
it does not work exactly like this but the result is the same): If the
graphic card needs to draw a pixel on a screen it first looks if this
pixel is on a vertex. If it is, it can take the color of the vertex and
draw a pixel with this color. If not, the graphic card looks at which
triangle this pixel belongs. Then it looks at where the vertices of this
triangle are and calculates the distance to each of the vertices. Based
on this distance and the color of the vertices, it interpolates all color
components and draws a pixel with this color.
We've already seen that the graphic card does not care about the fact
that a color consists of the three parts R, G and B. The good thing
about this is that the graphic card can do the calculations for R
independent of the other parts, as is the case for G and B. You may ask,
"why should I care"? The advantage is that the graphic card can do
calculations for each part in parallel. A graphic card is in general
extremely specialized in parallel computing. This is also true for vertex
shaders and pixel shaders. Each calculation for a vertex or pixel is done
individually. A vertex never knows how what his neighbor looks like and
a pixel never knows what his neighbor's color is. This is a reason why
graphic card vendors can improve the performance of GPUs faster then CPUs.
Vertex and pixel shaders are inherently parallel. The disadvantage of
this is that if you need to do some calculations with respect to the
neighboring pixel or vertex, you have to create a complex setup that often
(but not always) is not fast enough for 60+ FPS games.
A blur filter (like in the glow example) is an example of such a setup.
You need at least two passes to create such an effect.
"""
cubes = []
for x in [-3.0, 0.0, 3.0]:
cube = modelCube.copyTo(root)
cube.setPos(x, 0.0, 0.0)
cubes += [ cube ]
"""
DIRTY
Look at the textures first with any image viewer. Enable the textures afterwards
and see how they are blended together with the colors.
"""
#root.setTexture(stageArrow, textureArrow)
#root.setTexture(stageCircle, textureCircle)
"""
DIRTY
Also try to enable the textures not on all cubes at the same time. To test this
remove/comment the preceding two lines.
"""
#cubes[0].setTexture(stageArrow, textureArrow)
#cubes[1].setTexture(stageCircle, textureCircle)
#cubes[2].setTexture(stageArrow, textureArrow)
#cubes[2].setTexture(stageCircle, textureCircle)
"""
Exit the application.
"""
base.accept("escape", sys.exit)
"""
Use oobe mode to move around the camera.
"""
base.accept("o", base.oobe)
"""
Start an interval that rotates all cubes independently.
"""
def animate(t):
for i in range(len(cubes)):
cubes[i].setH(t * (2.0 ** i))
interval = LerpFunc(animate, 5.0, 0.0, 360.0)
base.accept("i", interval.start)
"""
Move all cubes (you should understand why all three and not only one).
"""
def move(x, y, z):
root.setX(root.getX() + x)
root.setY(root.getY() + y)
root.setZ(root.getZ() + z)
base.accept("d", move, [1.0, 0.0, 0.0])
base.accept("a", move, [-1.0, 0.0, 0.0])
base.accept("w", move, [0.0, 1.0, 0.0])
base.accept("s", move, [0.0, -1.0, 0.0])
base.accept("e", move, [0.0, 0.0, 1.0])
base.accept("q", move, [0.0, 0.0, -1.0])
run()
Show details
Hide details
Change log
r43
by Azraiyl on Jun 23, 2009
Diff
ShaderLibrary FX Composer project added.
Go to:
/trunk/0.py
/trunk/ShaderLibrary
/trunk/ShaderLibrary/Document.dae
/trunk/ShaderLibrary/Functions.cgfx
...nk/ShaderLibrary/MetaObject.cgfx
/trunk/ShaderLibrary/MetaScene.cgfx
/trunk/ShaderLibrary/SSAO.cgfx
...derLibrary/ShaderLibrary.fxcproj
.../ShaderLibrary/Superformula.cgfx
...nk/ShaderLibrary/TestObject.cgfx
/trunk/ShaderLibrary/TestScene.cgfx
...nk/ShaderLibrary/TestVolume.cgfx
...haderLibrary/cube-negative-x.jpg
...haderLibrary/cube-negative-y.jpg
...haderLibrary/cube-negative-z.jpg
...haderLibrary/cube-positive-x.jpg
...haderLibrary/cube-positive-y.jpg
...haderLibrary/cube-positive-z.jpg
/trunk/ShaderLibrary/cube.dds
...nk/ShaderLibrary/grid-albedo.png
/trunk/ShaderLibrary/grid-gloss.png
...nk/ShaderLibrary/grid-height.png
...nk/ShaderLibrary/grid-normal.png
/trunk/ShaderLibrary/makecube.bat
/trunk/ShaderLibrary/makecube.txt
/trunk/ShaderLibrary/makenoise.py
/trunk/ShaderLibrary/makesphere.py
/trunk/ShaderLibrary/makevolume.bat
/trunk/ShaderLibrary/makevolume.txt
...brary/noise-color-normalized.png
...haderLibrary/noise-grayscale.png
...k/ShaderLibrary/sharpangle.blend
/trunk/ShaderLibrary/volume-0.png
/trunk/ShaderLibrary/volume-1.png
/trunk/ShaderLibrary/volume-2.png
/trunk/ShaderLibrary/volume-3.png
/trunk/ShaderLibrary/volume.dds
Project members,
sign in
to write a code review
Older revisions
All revisions of this file
File info
Size: 7458 bytes, 195 lines
View raw file
Hosted by