/
azul3d_rtt.go
180 lines (150 loc) · 4.47 KB
/
azul3d_rtt.go
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
// Copyright 2014 The Azul3D Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Example - Demonstrates texture coordinates.
package main
import (
"image"
"log"
"azul3d.org/engine/gfx"
"azul3d.org/engine/gfx/camera"
"azul3d.org/engine/gfx/gfxutil"
"azul3d.org/engine/gfx/window"
"azul3d.org/engine/keyboard"
"azul3d.org/engine/lmath"
"azul3d.org/examples/abs"
)
// gfxLoop is responsible for drawing things to the window.
func gfxLoop(w window.Window, d gfx.Device) {
// Create a new perspective (3D) camera.
cam := camera.New(d.Bounds())
// Move the camera back two units away from the card.
cam.SetPos(lmath.Vec3{0, -2, 0})
// Create a texture to hold the color data of our render-to-texture.
rtColor := gfx.NewTexture()
rtColor.MinFilter = gfx.LinearMipmapLinear
rtColor.MagFilter = gfx.Linear
// Choose a render to texture format.
cfg := d.Info().RTTFormats.ChooseConfig(gfx.Precision{
// We want 24/bpp RGB color buffer.
RedBits: 8, GreenBits: 8, BlueBits: 8,
// We could also request a depth or stencil buffer here, by simply
// using the lines:
// DepthBits: 24,
// StencilBits: 24,
}, true)
// Print the configuration we chose.
log.Printf("RTT ColorFormat=%v, DepthFormat=%v, StencilFormat=%v\n", cfg.ColorFormat, cfg.DepthFormat, cfg.StencilFormat)
// Color buffer will go into our rtColor texture.
cfg.Color = rtColor
// We will render to a 512x512 area.
cfg.Bounds = image.Rect(0, 0, 512, 512)
// Create our render-to-texture canvas.
rtCanvas := d.RenderToTexture(cfg)
if rtCanvas == nil {
// Important! Check if the canvas is nil. If it is their graphics
// hardware doesn't support render to texture. Sorry!
log.Fatal("Graphics hardware does not support render to texture.")
}
// Read the GLSL shaders from disk.
shader, err := gfxutil.OpenShader(abs.Path("azul3d_rtt/rtt"))
if err != nil {
log.Fatal(err)
}
// Create a card mesh.
cardMesh := gfx.NewMesh()
cardMesh.Vertices = []gfx.Vec3{
// Bottom-left triangle.
{-1, 0, -1},
{1, 0, -1},
{-1, 0, 1},
// Top-right triangle.
{-1, 0, 1},
{1, 0, -1},
{1, 0, 1},
}
cardMesh.TexCoords = []gfx.TexCoordSet{
{
Slice: []gfx.TexCoord{
{0, 1},
{1, 1},
{0, 0},
{0, 0},
{1, 1},
{1, 0},
},
},
}
// Create a card object.
card := gfx.NewObject()
card.State = gfx.NewState()
card.FaceCulling = gfx.NoFaceCulling
card.AlphaMode = gfx.AlphaToCoverage
card.Shader = shader
card.Textures = []*gfx.Texture{rtColor}
card.Meshes = []*gfx.Mesh{cardMesh}
// Create an event mask for the events we are interested in.
evMask := window.FramebufferResizedEvents
evMask |= window.KeyboardTypedEvents
// Create a channel of events.
event := make(chan window.Event, 256)
// Have the window notify our channel whenever events occur.
w.Notify(event, evMask)
// Draw some colored stripes onto the render to texture canvas. The result
// is stored in the rtColor texture, and we can then display it on a card
// below without even rendering the stripes every frame.
stripeColor1 := gfx.Color{1, 0, 0, 1} // red
stripeColor2 := gfx.Color{0, 1, 0, 1} // green
stripeWidth := 12 // pixels
flipColor := false
b := rtCanvas.Bounds()
for i := 0; (i * stripeWidth) < b.Dx(); i++ {
flipColor = !flipColor
x := i * stripeWidth
dst := image.Rect(x, b.Min.Y, x+stripeWidth, b.Max.Y)
if flipColor {
rtCanvas.Clear(dst, stripeColor1)
} else {
rtCanvas.Clear(dst, stripeColor2)
}
}
// Render the rtCanvas to the rtColor texture.
rtCanvas.Render()
for {
// Handle each pending event.
window.Poll(event, func(e window.Event) {
switch ev := e.(type) {
case window.FramebufferResized:
// Update the camera's projection matrix for the new width and
// height.
cam.Update(d.Bounds())
case keyboard.Typed:
if ev.S == "m" || ev.S == "M" {
// Toggle mipmapping.
if rtColor.MinFilter == gfx.LinearMipmapLinear {
rtColor.MinFilter = gfx.Linear
} else {
rtColor.MinFilter = gfx.LinearMipmapLinear
}
}
}
})
// Rotate the card on the Z axis 15 degrees/sec.
rot := card.Rot()
card.SetRot(lmath.Vec3{
X: rot.X,
Y: rot.Y,
Z: rot.Z + (15 * d.Clock().Dt()),
})
// Clear color and depth buffers.
d.Clear(d.Bounds(), gfx.Color{1, 1, 1, 1})
d.ClearDepth(d.Bounds(), 1.0)
// Draw the card.
d.Draw(d.Bounds(), card, cam)
// Render the frame.
d.Render()
}
}
func main() {
window.Run(gfxLoop, nil)
}