// drawString draws the same string twice with a colour and location offset, // to simulate a drop-shadow. It does so for each loaded font. func drawString(x, y float32, str string) error { for i := range fonts { if fonts[i] == nil { continue } // We need to offset each string by the height of the // font. To ensure they don't overlap each other. _, h := fonts[i].GlyphBounds() y := y + float32(i*h) gl.Color4f(0.1, 0.1, 0.1, 0.7) err := fonts[i].Printf(x+2, y+2, str) if err != nil { return err } gl.Color4f(1, 1, 1, 1) err = fonts[i].Printf(x, y, str) if err != nil { return err } } return nil }
// drawString draws the same string for each loaded font. func drawString(x, y float32, str string) error { for i := range fonts { if fonts[i] == nil { continue } // We need to offset each string by the height of the // font. To ensure they don't overlap each other. _, h := fonts[i].GlyphBounds() y := y + float32(i*h) // Draw a rectangular backdrop using the string's metrics. sw, sh := fonts[i].Metrics(SampleString) gl.Color4f(0.1, 0.1, 0.1, 0.7) gl.Rectf(x, y, x+float32(sw), y+float32(sh)) // Render the string. gl.Color4f(1, 1, 1, 1) err := fonts[i].Printf(x, y, str) if err != nil { return err } } return nil }
func drawInfoBox(x, y float64, fontSize, iteration, nThreads int, execTime string) { // TODO font, err := loadFont("/Users/nils/tmp/DejaVuSansMono.ttf", int32(fontSize)) if err != nil { log.Printf("LoadFont: %v", err) return } firstLine := fmt.Sprintf("Iteration nr %d", iteration) secondLine := fmt.Sprintf("Took %s using %d threads.", execTime, nThreads) w1, h1 := font.Metrics(firstLine) w2, h2 := font.Metrics(secondLine) var w int if w1 > w2 { w = w1 } else { w = w2 } w += 3 h := h1 + h2 gl.Color4f(1, 1, 1, 0.7) gl.Rectd(x, y, x+float64(w), y+float64(h)) gl.Color4f(0, 0, 0, 1) err = font.Printf(float32(x)+3, float32(y), firstLine) if err != nil { log.Printf("Something went wrong when drawing fonts: %v", err) return } err = font.Printf(float32(x)+3, float32(y+float64(h1)), secondLine) if err != nil { log.Printf("Something went wrong when drawing fonts: %v", err) return } }
func initGL() (err error) { if err = loadTextures(); err != nil { return } gl.ShadeModel(gl.SMOOTH) gl.ClearColor(0, 0, 0, 0) gl.ClearDepth(1) gl.DepthFunc(gl.LEQUAL) gl.Hint(gl.PERSPECTIVE_CORRECTION_HINT, gl.NICEST) gl.Enable(gl.TEXTURE_2D) gl.Enable(gl.DEPTH_TEST) //alpha通道的值为 0.0意味着物体材质是完全透明的。1.0 则意味着完全不透明 //以全亮度绘制此物体,并对其进行50%的alpha混合(半透明)。 //当混合选项打开时,此物体将会产生50%的透明效果 gl.Color4f(1, 1, 1, 0.5) //全亮度, 50% Alpha 混合 gl.BlendFunc(gl.SRC_ALPHA, gl.ONE) //基于源象素alpha通道值的半透明混合函数 gl.Lightfv(gl.LIGHT1, gl.AMBIENT, ambient) gl.Lightfv(gl.LIGHT1, gl.AMBIENT, diffuse) gl.Lightfv(gl.LIGHT1, gl.POSITION, lightpos) gl.Enable(gl.LIGHT1) return }
// OpenGL draw function func draw() { gl.Clear(gl.COLOR_BUFFER_BIT) gl.Enable(gl.BLEND) gl.Enable(gl.POINT_SMOOTH) gl.Enable(gl.LINE_SMOOTH) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.LoadIdentity() gl.Begin(gl.LINES) gl.Color3f(.2, .2, .2) for i := range staticLines { x := staticLines[i].GetAsSegment().A.X y := staticLines[i].GetAsSegment().A.Y gl.Vertex3f(float32(x), float32(y), 0) x = staticLines[i].GetAsSegment().B.X y = staticLines[i].GetAsSegment().B.Y gl.Vertex3f(float32(x), float32(y), 0) } gl.End() gl.Color4f(.3, .3, 1, .8) // draw balls for _, ball := range balls { gl.PushMatrix() pos := ball.Body.Position() rot := ball.Body.Angle() * chipmunk.DegreeConst gl.Translatef(float32(pos.X), float32(pos.Y), 0.0) gl.Rotatef(float32(rot), 0, 0, 1) drawCircle(float64(ballRadius), 60) gl.PopMatrix() } }
func (pen *Pen) lineTo(x, y int) { gl.Enable(gl.BLEND) gl.Enable(gl.POINT_SMOOTH) gl.Enable(gl.LINE_SMOOTH) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.Color4f(0.0, 0.0, 0.0, 0.1) gl.Begin(gl.LINES) var p [2]int for i := range pen.points { p = pen.points[i] if p[0] == 0 && p[1] == 0 { continue } if distanceTo(x, y, p[0], p[1]) < 10.0 { gl.Vertex2i(x, y) gl.Vertex2i(p[0], p[1]) } } gl.End() pen.n = (pen.n + 1) % len(pen.points) pen.points[pen.n][0] = x pen.points[pen.n][1] = y pen.moveTo(x, y) }
func (m *Map) Draw() { gl.PushMatrix() gl.PushAttrib(gl.CURRENT_BIT | gl.ENABLE_BIT | gl.LIGHTING_BIT | gl.POLYGON_BIT | gl.LINE_BIT) gl.EnableClientState(gl.VERTEX_ARRAY) gl.VertexPointer(3, gl.FLOAT, 0, m.vertices) gl.EnableClientState(gl.NORMAL_ARRAY) gl.NormalPointer(gl.FLOAT, 0, m.normals) // gl.EnableClientState(gl.TEXTURE_COORD_ARRAY) // gl.TexCoordPointer(2, gl.FLOAT, 0, m.texcoords) gl.EnableClientState(gl.COLOR_ARRAY) gl.ColorPointer(3, gl.FLOAT, 0, m.colors) // draw solids gl.Enable(gl.COLOR_MATERIAL) // gl.DrawArrays(gl.TRIANGLE_STRIP, 0, len(m.vertices)/3) gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE) gl.LineWidth(1.0) gl.Color4f(1, 1, 1, 1) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, len(m.vertices)/3) gl.PopAttrib() gl.PopMatrix() }
func (p *Pipe) Render() { gl.Color4f(0.0, 255.0, 0.0, 1.0) rimHeight := 20 utils.TexturedQuad(p.pipe, p.X, 0, p.Width, p.Y-rimHeight) utils.TexturedQuad(p.rim, p.X, p.Y-rimHeight, p.Width, rimHeight) utils.TexturedQuad(p.rim, p.X, p.Y+p.Height, p.Width, rimHeight) utils.TexturedQuad(p.pipe, p.X, p.Y+p.Height+rimHeight, p.Width, p.ScreenHeight-p.Height) }
func (f *Font) Printf(x float64, y float64, format string, a ...interface{}) (err error) { var ( str string //sw int //sh int ) str = fmt.Sprintf(format, a...) gl.Color4f(1, 1, 1, 1) err = f.font.Printf(float32(x), float32(y), str) return }
func drawHex(x, y, kind int, alpha float32) { if kind == 6 { gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.REPLACE) starTex.Bind(gl.TEXTURE_2D) gl.Begin(gl.QUADS) gl.TexCoord2f(0, 0) gl.Vertex2i(x, y) gl.TexCoord2f(0, 1) gl.Vertex2i(x, y+HEX_HEIGHT) gl.TexCoord2f(1, 1) gl.Vertex2i(x+HEX_WIDTH, y+HEX_HEIGHT) gl.TexCoord2f(1, 0) gl.Vertex2i(x+HEX_WIDTH, y) gl.End() } else { gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) var r, g, b float32 switch kind { case 0: r = 1 case 1: g = 1 case 2: b = 1 case 3: r = 1 g = 1 case 4: r = 1 b = 1 case 5: g = 1 - 222/255 b = 1 } hexTex.Bind(gl.TEXTURE_2D) gl.Begin(gl.QUADS) if alpha < 1 { gl.Color4f(r, g, b, alpha) } else { gl.Color3f(r, g, b) } gl.TexCoord2f(0, 0) gl.Vertex2i(x, y) gl.TexCoord2f(0, 1) gl.Vertex2i(x, y+HEX_HEIGHT) gl.TexCoord2f(1, 1) gl.Vertex2i(x+HEX_WIDTH, y+HEX_HEIGHT) gl.TexCoord2f(1, 0) gl.Vertex2i(x+HEX_WIDTH, y) gl.End() } }
func (rw *RenderWindow) draw() { gl.Clear(gl.COLOR_BUFFER_BIT) gl.Enable(gl.LINE_SMOOTH) for chanIdx, channel := range rw.Channels { color := channel.GetColor() gl.Color4f(color[0], color[1], color[2], color[3]) gl.Begin(gl.LINES) lastY := int64(0) for i := 0; i < len(rw.renderBuffers[chanIdx]); i += 1 { y := rw.Height - (rw.renderBuffers[chanIdx][i] * rw.Height / 1024) gl.Vertex2i(i-1, int(lastY)) gl.Vertex2i(i, int(y)) lastY = y } gl.Flush() gl.End() } glfw.SwapBuffers() }
func TexturedQuad(t *glh.Texture, x, y, w, h int) { glh.With(t, func() { gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.Color4f(255.0, 255.0, 255.0, 1.0) gl.Begin(gl.TRIANGLE_FAN) gl.TexCoord2f(0, 0) gl.Vertex2i(x, y) gl.TexCoord2f(1, 0) gl.Vertex2i(x+w, y) gl.TexCoord2f(1, 1) gl.Vertex2i(x+w, y+h) gl.TexCoord2f(0, 1) gl.Vertex2i(x, y+h) gl.End() }) }
// Draw a test pattern func TestWindowCoordsA(t *testing.T) { gltest.OnTheMainThread(func() { gltest.SetWindowSize(40, 5) w, h := GetViewportWH() With(WindowCoords{}, func() { // So that we draw in the middle of the pixel gl.Translated(0.5, 0.5, 0) gl.Color4f(1, 1, 1, 1) With(Primitive{gl.POINTS}, func() { for i := 0; i < w+1; i += 2 { gl.Vertex2i(i, h/2) } }) }) }, func() { CaptureToPng("TestWindowCoordsA.png") }) }
func initGL() (err error) { if err = loadTextures(); err != nil { return } gl.ShadeModel(gl.SMOOTH) gl.ClearColor(0, 0, 0, 0) gl.ClearDepth(1) gl.DepthFunc(gl.LEQUAL) gl.Hint(gl.PERSPECTIVE_CORRECTION_HINT, gl.NICEST) gl.Enable(gl.TEXTURE_2D) gl.Enable(gl.DEPTH_TEST) gl.Color4f(1, 1, 1, 0.5) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE) gl.Lightfv(gl.LIGHT1, gl.AMBIENT, ambient) gl.Lightfv(gl.LIGHT1, gl.AMBIENT, diffuse) gl.Lightfv(gl.LIGHT1, gl.POSITION, lightpos) gl.Enable(gl.LIGHT1) return }
func (sg *OpenGLGraphics) Text(x, y int, t string, align string, rot int, f chart.Font) { if len(align) == 1 { align = "c" + align } _, fh, _ := sg.FontMetrics(f) tex := glh.MakeText(t, float64(fh)) tex.Flipped = true defer tex.Destroy() switch align[0] { case 'b': case 'c': y += fh / 2 case 't': y += fh default: log.Panicf("Unknown alignment: ", align) } switch align[1] { case 'l': case 'c': x -= tex.W / 2 case 'r': x -= tex.W default: log.Panicf("Unknown alignment: ", align) } if f.Color == nil { gl.Color4f(1, 1, 1, 1) } else { glh.ColorC(f.Color) } glh.With(tex, func() { tex.Draw(x, y) }) }
// Used in classic render mode. // Defines vertex colors. func (a *Attr) color(i int) { i *= a.size switch a.size { case 3: switch v := a.data.(type) { case []int8: gl.Color3b(v[i], v[i+1], v[i+2]) case []uint8: gl.Color3ub(v[i], v[i+1], v[i+2]) case []int16: gl.Color3s(v[i], v[i+1], v[i+2]) case []int32: gl.Color3i(int(v[i]), int(v[i+1]), int(v[i+2])) case []float32: gl.Color3f(v[i], v[i+1], v[i+2]) case []float64: gl.Color3d(v[i], v[i+1], v[i+2]) } case 4: switch v := a.data.(type) { case []int8: gl.Color4b(v[i], v[i+1], v[i+2], v[i+3]) case []uint8: gl.Color4ub(v[i], v[i+1], v[i+2], v[i+3]) case []int16: gl.Color4s(v[i], v[i+1], v[i+2], v[i+3]) case []int32: gl.Color4i(int(v[i]), int(v[i+1]), int(v[i+2]), int(v[i+3])) case []float32: gl.Color4f(v[i], v[i+1], v[i+2], v[i+3]) case []float64: gl.Color4d(v[i], v[i+1], v[i+2], v[i+3]) } } }
// Draws a cross on the screen with known lengths, useful for understanding // screen dimensions func DebugLines() { gl.MatrixMode(gl.PROJECTION) gl.PushMatrix() //gl.LoadIdentity() //gl.Ortho(-2.1, 6.1, -4, 8, 1, -1) gl.MatrixMode(gl.MODELVIEW) gl.PushMatrix() gl.LoadIdentity() gl.LoadIdentity() gl.LineWidth(5) gl.Color4f(1, 1, 0, 1) gl.Begin(gl.LINES) gl.Vertex2d(0, -1.6) gl.Vertex2d(0, 0.8) gl.Vertex2d(-0.8, 0) gl.Vertex2d(0.8, 0) gl.End() gl.PopMatrix() gl.MatrixMode(gl.PROJECTION) gl.PopMatrix() gl.MatrixMode(gl.MODELVIEW) }
// Draw a test pattern func TestWindowCoords(t *testing.T) { gltest.OnTheMainThread(func() { gltest.SetWindowSize(40, 40) w, h := GetViewportWH() With(WindowCoords{}, func() { // So that we draw in the middle of the pixel gl.Translated(0.5, 0.5, 0) // Draw stripes stride := 1 internal_n := 4 for b := 0; b < w/2-internal_n*stride; b += stride { if b/stride%2 == 0 { gl.Color4f(1, 1, 1, 1) } else { gl.Color4f(1, 0, 0, 1) } With(Primitive{gl.LINE_LOOP}, func() { gl.Vertex2i(b, b) gl.Vertex2i(w-b, b) gl.Vertex2i(w-b, h-b) gl.Vertex2i(b, h-b) }) } // Central white, green, blue checked pattern gl.PointSize(2) With(Primitive{gl.POINTS}, func() { gl.Color4f(1, 1, 1, 1) gl.Vertex2i(w/2-2, h/2-2) gl.Vertex2i(w/2+2, h/2+2) gl.Color4f(0, 1, 0, 1) gl.Vertex2i(w/2+2, h/2-2) gl.Vertex2i(w/2-2, h/2+2) gl.Color4f(1, 1, 1, 1) gl.Vertex2i(w/2, h/2) }) // Blue horizontal line to show With(Primitive{gl.LINE_LOOP}, func() { gl.Color4f(0, 0, 1, 1) gl.Vertex2i(0, h/2-4) gl.Vertex2i(w, h/2-4) gl.Vertex2i(w/2-4, 0) gl.Vertex2i(w/2-4, h) }) // Remove some pixels near the boundaries gl.PointSize(1) gl.Color4f(0, 0, 0, 1) With(Primitive{gl.POINTS}, func() { // Black dot in top left gl.Vertex2i(0, 0) // Off the top right (should not be visible) gl.Vertex2i(w, 0) // Bottom left pixel (should be visible as a black dot) gl.Vertex2i(0, h-1) }) }) }, func() { CaptureToPng("TestWindowCoords.png") }) }
func main_loop(data *ProgramData) { start := time.Now() frames := 0 lastblocks := 0 // Frame counter go func() { for { time.Sleep(time.Second) if *verbose { memstats := new(runtime.MemStats) runtime.ReadMemStats(memstats) fps := float64(frames) / time.Since(start).Seconds() blocks := len(data.blocks) bps := float64(blocks-lastblocks) / time.Since(start).Seconds() lastblocks = blocks log.Printf("fps = %5.2f; blocks = %4d; bps = %5.2f sparemem = %6d MB; alloc'd = %6.6f; (+footprint = %6.6f)", fps, len(data.blocks), bps, SpareRAM(), float64(memstats.Alloc)/1024/1024, float64(memstats.Sys-memstats.Alloc)/1024/1024) PrintTimers(frames) } start = time.Now() frames = 0 } }() // Necessary at the moment to prevent eventual OOM go func() { for { time.Sleep(5 * time.Second) if *verbose { log.Print("GC()") } runtime.GC() if *verbose { GCStats() } } }() var i int64 = -int64(*nback) // TODO(pwaller): Make this work again // text := glh.MakeText(data.filename, 32) // Location of mouse in record space var rec, rec_actual int64 = 0, 0 var stacktext, dwarftext []*glh.Text var recordtext *glh.Text = nil var mousex, mousey, mousedownx, mousedowny int var mousepx, mousepy float64 var lbutton bool escape_hit := false glfw.SetMouseWheelCallback(func(pos int) { nback_prev := *nback if pos < 0 { *nback = 40 * 1024 << uint(-pos) } else { *nback = 40 * 1024 >> uint(pos) } //log.Print("Mousewheel position: ", pos, " nback: ", *nback) if rec == 0 { return } // mouse cursor is at screen "rec_actual", and it should be after // the transformation // We need to adjust `i` to keep this value constant: // rec_actual == i + int64(constpart * float64(*nback)) // where constpart <- (-const + 2.) / 4. // (that way, the mouse is still pointing at the same place after scaling) constpart := float64(rec_actual-i) / float64(nback_prev) rec_actual_after := i + int64(constpart*float64(*nback)) delta := rec_actual_after - rec_actual i -= delta // Ensure the mouse cursor position doesn't change when zooming rec = rec_actual - i }) update_text := func() { if DoneThisFrame(RenderText) { return } if recordtext != nil { recordtext.Destroy() recordtext = nil } //r := 0 //data.GetRecord(rec_actual) //if r != nil { //log.Print(data.records[rec_actual]) //recordtext = MakeText(r.String(), 32) //} for j := range stacktext { stacktext[j].Destroy() } // TODO: Load records on demand if false { stack := data.GetStackNames(rec_actual) stacktext = make([]*glh.Text, len(stack)) for j := range stack { stacktext[j] = glh.MakeText(stack[j], 32) } } } glfw.SetMouseButtonCallback(func(button, action int) { switch button { case glfw.Mouse1: switch action { case glfw.KeyPress: mousedownx, mousedowny = mousex, mousey lbutton = true r := data.GetRecord(rec_actual) if r != nil { if r.Type == MEMA_ACCESS { log.Print(r) ma := r.MemAccess() dwarf := data.GetDwarf(ma.Pc) log.Print("Can has dwarf? ", len(dwarf)) for i := range dwarf { log.Print(" ", dwarf[i]) //recordtext = MakeText(data.records[rec_actual].String(), 32) } log.Print("") for j := range dwarftext { dwarftext[j].Destroy() } dwarftext = make([]*glh.Text, len(dwarf)) for j := range dwarf { dwarftext[j] = glh.MakeText(fmt.Sprintf("%q", dwarf[j]), 32) } } //recordtext = MakeText(data.records[rec_actual].String(), 32) } case glfw.KeyRelease: lbutton = false } } }) glfw.SetMousePosCallback(func(x, y int) { px, py := glh.WindowToProj(x, y) // Record index rec = int64((py+2)*float64(*nback)/4. + 0.5) rec_actual = rec + i dpy := py - mousepy di := int64(-dpy * float64(*nback) / 4.) if lbutton { i += di } mousepx, mousepy = px, py mousex, mousey = x, y //log.Printf("Mouse motion: (%3d, %3d), (%f, %f), (%d, %d) dpy=%f di=%d", //x, y, px, py, rec, rec_actual, dpy, di) update_text() }) glfw.SetKeyCallback(func(key, state int) { switch key { case glfw.KeyEsc: escape_hit = true } }) draw_mousepoint := func() { // Draw the mouse point glh.With(glh.Matrix{gl.MODELVIEW}, func() { gl.Translated(0, -2, 0) gl.Scaled(1, 4/float64(*nback), 1) gl.Translated(0, float64(rec), 0) gl.PointSize(10) glh.With(glh.Primitive{gl.POINTS}, func() { gl.Color4f(1, 1, 1, 1) gl.Vertex3d(mousepx, 0, 0) }) }) } draw_text := func() { // Draw any text glh.With(glh.WindowCoords{}, func() { w, h := glh.GetViewportWHD() glh.With(glh.Attrib{gl.ENABLE_BIT}, func() { gl.Enable(gl.TEXTURE_2D) // text.Draw(0, 0) for text_idx := range stacktext { stacktext[text_idx].Draw(int(w*0.55), int(h)-35-text_idx*16) } for text_idx := range dwarftext { dwarftext[text_idx].Draw(int(w*0.55), 35+text_idx*16) } if recordtext != nil { recordtext.Draw(int(w*0.55), 35) } }) }) } Draw = func() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) // Draw the memory access/function data data.Draw(i, *nback) draw_mousepoint() draw_text() // Visible region quad // gl.Color4f(1, 1, 1, 0.25) // DrawQuadd(-2.1, -2.25, 4.4, 2.1 - -2.25) // StatsHUD() } interrupt := make(chan os.Signal) signal.Notify(interrupt, os.Interrupt) ctrlc_hit := false go func() { <-interrupt ctrlc_hit = true }() done := false for !done { done_this_frame = make(map[WorkType]bool) glh.With(&Timer{Name: "Draw"}, func() { Draw() }) glfw.SwapBuffers() DoMainThreadWork() done = ctrlc_hit || escape_hit || glfw.WindowParam(glfw.Opened) == 0 frames += 1 } }
func main() { var err error if err = glfw.Init(); err != nil { fmt.Fprintf(os.Stderr, "[e] %v\n", err) return } defer glfw.Terminate() w, h := 1980, 1080 // w, h := 1280, 768 if err = glfw.OpenWindow(w, h, 8, 8, 8, 16, 0, 32, glfw.Fullscreen); err != nil { fmt.Fprintf(os.Stderr, "[e] %v\n", err) return } defer glfw.CloseWindow() glfw.SetSwapInterval(1) glfw.SetWindowTitle("Debris") quadric = glu.NewQuadric() gl.Enable(gl.CULL_FACE) gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LEQUAL) gl.Enable(gl.NORMALIZE) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.ShadeModel(gl.SMOOTH) gl.Enable(gl.LIGHTING) var ( ambient = []float32{0.1, 0.3, 0.6, 1} diffuse = []float32{1, 1, 0.5, 1} specular = []float32{0.4, 0.4, 0.4, 1} light_position = []float32{1, 0, 0, 0} // mat_specular []float32 = []float32{1, 1, 0.5, 1} mat_specular = []float32{1, 1, 0.75, 1} mat_shininess = float32(120) // light_position []float32 = []float32{0.0, 0.0, 1.0, 0.0} ) const ( fov = 1.1 // degrees znear = 145 zfar = 155 camera_z_offset = -150 camera_x_rotation = 0 // degrees // camera_x_rotation = 20 // degrees starfield_fov = 45 faces = 1000 earth_radius = 1 ) gl.Lightfv(gl.LIGHT1, gl.AMBIENT, ambient) gl.Lightfv(gl.LIGHT1, gl.DIFFUSE, diffuse) gl.Lightfv(gl.LIGHT1, gl.SPECULAR, specular) gl.Lightfv(gl.LIGHT1, gl.POSITION, light_position) gl.Enable(gl.LIGHT1) mat_emission := []float32{0, 0, 0.1, 1} gl.Materialfv(gl.FRONT_AND_BACK, gl.EMISSION, mat_emission) gl.Materialfv(gl.FRONT_AND_BACK, gl.SPECULAR, mat_specular) gl.Materialf(gl.FRONT_AND_BACK, gl.SHININESS, mat_shininess) gl.ClearColor(0.02, 0.02, 0.02, 1) gl.ClearDepth(1) gl.ClearStencil(0) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) b := createBuffer() planetoids := []*Planetoid{} for i := 0; i < 1000; i++ { p := &Planetoid{ apogee: 1.2 + rand.Float64()*0.7, perigee: 1.5, // inclination: 45, inclination: rand.Float64()*20 - 10, // inclination: 0, phase0: rand.Float64() * 360, rising_node: rand.Float64() * 10, phase: 0, // radius: rand.Float32()*0.05 + 0.01, //float32(r), radius: rand.Float32()*0.0125 + 0.005, //float32(r), // quadric: glu.NewQuadric(), circle: b, } planetoids = append(planetoids, p) } // Initial projection matrix: var aspect float64 glfw.SetWindowSizeCallback(func(w, h int) { gl.Viewport(0, 0, w, h) gl.MatrixMode(gl.PROJECTION) gl.LoadIdentity() aspect = float64(w) / float64(h) glu.Perspective(fov, aspect, znear, zfar) }) d := float64(0) wireframe := false atmosphere := false polar := false rotating := false front := false earth := true cone := true shadowing := true tilt := false running := true glfw.SetKeyCallback(func(key, state int) { if state != glfw.KeyPress { // Don't act on key coming up return } switch key { case 'A': atmosphere = !atmosphere case 'C': cone = !cone case 'E': earth = !earth case 'R': rotating = !rotating case 'F': front = !front if front { gl.FrontFace(gl.CW) } else { gl.FrontFace(gl.CCW) } case 'S': shadowing = !shadowing case 'T': tilt = !tilt case 'W': wireframe = !wireframe method := gl.GLenum(gl.FILL) if wireframe { method = gl.LINE } gl.PolygonMode(gl.FRONT_AND_BACK, method) case glfw.KeyF2: println("Screenshot captured") // glh.CaptureToPng("screenshot.png") w, h := glh.GetViewportWH() im := image.NewRGBA(image.Rect(0, 0, w, h)) glh.ClearAlpha(1) gl.Flush() glh.CaptureRGBA(im) go func() { fd, err := os.Create("screenshot.png") if err != nil { panic("Unable to open file") } defer fd.Close() png.Encode(fd, im) }() case 'Q', glfw.KeyEsc: running = !running case glfw.KeySpace: polar = !polar } }) _ = rand.Float64 stars := glh.NewMeshBuffer( glh.RenderArrays, glh.NewPositionAttr(3, gl.DOUBLE, gl.STATIC_DRAW), glh.NewColorAttr(3, gl.DOUBLE, gl.STATIC_DRAW)) const Nstars = 50000 points := make([]float64, 3*Nstars) colors := make([]float64, 3*Nstars) for i := 0; i < Nstars; i++ { const R = 1 phi := rand.Float64() * 2 * math.Pi z := R * (2*rand.Float64() - 1) theta := math.Asin(z / R) points[i*3+0] = R * math.Cos(theta) * math.Cos(phi) points[i*3+1] = R * math.Cos(theta) * math.Sin(phi) points[i*3+2] = z const r = 0.8 v := rand.Float64()*r + (1 - r) colors[i*3+0] = v colors[i*3+1] = v colors[i*3+2] = v } stars.Add(points, colors) render_stars := func() { glh.With(glh.Attrib{gl.DEPTH_BUFFER_BIT | gl.ENABLE_BIT}, func() { gl.Disable(gl.LIGHTING) gl.PointSize(1) gl.Color4f(1, 1, 1, 1) gl.Disable(gl.DEPTH_TEST) gl.DepthMask(false) stars.Render(gl.POINTS) }) } render_scene := func() { // Update light position (sensitive to current modelview matrix) gl.Lightfv(gl.LIGHT1, gl.POSITION, light_position) gl.Lightfv(gl.LIGHT2, gl.POSITION, light_position) if earth { Sphere(earth_radius, faces) } unlit_points := glh.Compound(glh.Disable(gl.LIGHTING), glh.Primitive{gl.POINTS}) glh.With(unlit_points, func() { gl.Vertex3d(1, 0, 0) }) for _, p := range planetoids { const dt = 0.1 // TODO: Frame update p.Render(dt) } glh.With(glh.Disable(gl.LIGHTING), func() { // Atmosphere gl.Color4f(0.25, 0.25, 1, 0.1) if atmosphere && earth { Sphere(earth_radius*1.025, 100) } gl.PointSize(10) glh.With(glh.Primitive{gl.POINTS}, func() { gl.Color4f(1.75, 0.75, 0.75, 1) gl.Vertex3d(-1.04, 0, 0) }) }) } render_shadow_volume := func() { glh.With(glh.Attrib{ gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.ENABLE_BIT | gl.POLYGON_BIT | gl.STENCIL_BUFFER_BIT, }, func() { gl.Disable(gl.LIGHTING) if shadowing { // gl.Disable(gl.DEPTH_TEST) gl.DepthMask(false) gl.DepthFunc(gl.LEQUAL) gl.Enable(gl.STENCIL_TEST) gl.ColorMask(false, false, false, false) gl.StencilFunc(gl.ALWAYS, 1, 0xffffffff) } shadow_volume := func() { const sv_length = 2 const sv_granularity = 100 const sv_radius = earth_radius * 1.001 // Shadow cone glh.With(glh.Matrix{gl.MODELVIEW}, func() { gl.Rotatef(90, 1, 0, 0) gl.Rotatef(90, 0, -1, 0) gl.Color4f(0.5, 0.5, 0.5, 1) glu.Cylinder(quadric, sv_radius, sv_radius*1.05, sv_length, sv_granularity, 1) glu.Disk(quadric, 0, sv_radius, sv_granularity, 1) glh.With(glh.Matrix{gl.MODELVIEW}, func() { gl.Translated(0, 0, sv_length) glu.Disk(quadric, 0, sv_radius*1.05, sv_granularity, 1) }) }) for _, p := range planetoids { p.RenderShadowVolume() } } if cone { gl.FrontFace(gl.CCW) gl.StencilOp(gl.KEEP, gl.KEEP, gl.INCR) shadow_volume() gl.FrontFace(gl.CW) gl.StencilOp(gl.KEEP, gl.KEEP, gl.DECR) shadow_volume() } if shadowing { gl.StencilFunc(gl.NOTEQUAL, 0, 0xffffffff) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) gl.ColorMask(true, true, true, true) // gl.Disable(gl.STENCIL_TEST) gl.Disable(gl.DEPTH_TEST) gl.FrontFace(gl.CCW) // gl.Color4f(1, 0, 0, 0.75) gl.Color4f(0, 0, 0, 0.75) // gl.Color4f(1, 1, 1, 0.75) gl.LoadIdentity() gl.Translated(0, 0, camera_z_offset) // TODO: Figure out why this doesn't draw over the whole screen glh.With(glh.Disable(gl.LIGHTING), func() { glh.DrawQuadd(-10, -10, 20, 20) }) // gl.FrontFace(gl.CW) // gl.Enable(gl.LIGHTING) // gl.Disable(gl.LIGHT1) // render_scene() // gl.Enable(gl.LIGHT1) } }) } _ = render_stars for running { running = glfw.WindowParam(glfw.Opened) == 1 glfw.SwapBuffers() gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) rotation := func() { if tilt { gl.Rotated(20, 1, 0, 0) } if polar { gl.Rotated(90, 1, 0, 0) } gl.Rotated(d, 0, -1, 0) } // Star field glh.With(glh.Matrix{gl.PROJECTION}, func() { gl.LoadIdentity() glu.Perspective(starfield_fov, aspect, 0, 1) glh.With(glh.Matrix{gl.MODELVIEW}, func() { gl.LoadIdentity() rotation() render_stars() }) }) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Translated(0, 0, camera_z_offset) rotation() if rotating { d += 0.2 } _ = render_scene render_scene() _ = render_shadow_volume render_shadow_volume() } }
func (r *RenderTarget) Render(verts []Vertex, primType PrimitiveType, states RenderStates) { // Nothing to draw? if len(verts) == 0 { return } // First set the persistent OpenGL states if it's the very first call if !r.glStatesSet { r.resetGlStates() } // Check if the vertex count is low enough so that we can pre-transform them useVertexCache := len(verts) <= vertexCacheSize if useVertexCache { // Pre-transform the vertices and store them into the vertex cache for i := 0; i < len(verts); i++ { r.vpCache[i] = states.Transform.TransformPoint(verts[i].Pos) r.vcCache[i] = verts[i].Color r.vtCache[i] = verts[i].TexCoords } // Since vertices are transformed, we must use an identity transform to render them if !r.useVertexCache { r.applyTransform(IdentityTransform()) } } else { r.applyTransform(states.Transform) } // Apply the view if r.viewChanged { r.applyCurrentView() } // Apply the blend mode if states.BlendMode != r.lastBlendMode { r.applyBlendMode(states.BlendMode) } // Apply the texture var textureId uint64 if states.Texture != nil { textureId = states.Texture.cacheId } if textureId != r.lastTextureId { r.applyTexture(states.Texture) } // Apply the shader // TODO /*if states.shader { applyShader(states.shader); }*/ // ######################################### if !useVertexCache { // Find the OpenGL primitive type modes := [...]gl.GLenum{gl.POINTS, gl.LINES, gl.LINE_STRIP, gl.TRIANGLES, gl.TRIANGLE_STRIP, gl.TRIANGLE_FAN, gl.QUADS} mode := modes[primType] gl.Begin(mode) for i, _ := range verts { gl.TexCoord2f(verts[i].TexCoords.X, verts[i].TexCoords.Y) gl.Color4f(float32(verts[i].Color.R)/255, float32(verts[i].Color.G)/255, float32(verts[i].Color.B)/255, float32(verts[i].Color.A)/255) gl.Vertex2f(verts[i].Pos.X, verts[i].Pos.Y) } gl.End() } // ######################################### // Setup the pointers to the vertices' components // ... and if we already used it previously, we don't need to set the pointers again if useVertexCache { if !r.useVertexCache { gl.VertexPointer(2, gl.FLOAT, 0, r.vpCache[:]) gl.ColorPointer(4, gl.UNSIGNED_BYTE, 0, r.vcCache[:]) gl.TexCoordPointer(2, gl.FLOAT, 0, r.vtCache[:]) } // Find the OpenGL primitive type modes := [...]gl.GLenum{gl.POINTS, gl.LINES, gl.LINE_STRIP, gl.TRIANGLES, gl.TRIANGLE_STRIP, gl.TRIANGLE_FAN, gl.QUADS} mode := modes[primType] // Draw the primitives gl.DrawArrays(mode, 0, len(verts)) } // Unbind the shader, if any // TODO /*if (states.shader) { r.applyShader(nil) }*/ // Update the cache r.useVertexCache = useVertexCache }
func (block *Block) Draw(start, N int64, detailed bool) { if block.tex == nil { block.RequestTexture() } switch detailed { case true: block.detail_needed = true if block.vertex_data == nil { // Hey, we need vertices but don't have them! Let's fix that.. block.RequestVertices() } default: block.detail_needed = false } width := uint64(len(block.display_active_pages)) * *PAGE_SIZE if width == 0 { width = 1 } vc := glh.NewMeshBuffer(glh.RenderArrays, glh.NewPositionAttr(2, gl.FLOAT, gl.STATIC_DRAW), glh.NewPositionAttr(4, gl.UNSIGNED_INT, gl.STATIC_DRAW), ) colors := make([]int32, 0) positions := make([]float32, 0) // var vc glh.ColorVertices if *pageboundaries { // boundary_color := color.RGBA{64, 64, 64, 255} // If we try and draw too many of these, X will hang if width / *PAGE_SIZE < 10000 { for p := uint64(0); p <= width; p += *PAGE_SIZE { x := float32(p) / float32(width) x = (x - 0.5) * 4 colors = append(colors, 64, 64, 64, 255) positions = append(positions, x, float32(N)) // vc.Add(glh.ColorVertex{boundary_color, glh.Vertex{x, 0}}) // vc.Add(glh.ColorVertex{boundary_color, glh.Vertex{x, float32(N)}}) } } } var border_color [4]float64 gl.LineWidth(1) glh.With(&Timer{Name: "DrawPartial"}, func() { var x1, y1, x2, y2 float64 glh.With(glh.Matrix{gl.MODELVIEW}, func() { // TODO: A little less co-ordinate insanity? gl.Translated(0, -2, 0) gl.Scaled(1, 4/float64(*nback), 1) gl.Translated(0, -float64(start), 0) x1, y1 = glh.ProjToWindow(-2, 0) x2, y2 = glh.ProjToWindow(-2+WIDTH, float64(N)) }) border_color = [4]float64{1, 1, 1, 1} glh.With(glh.Matrix{gl.MODELVIEW}, func() { gl.Translated(0, -2, 0) gl.Scaled(1, 4/float64(*nback), 1) gl.Translated(0, -float64(start), 0) // Page boundaries // TODO: Use different blending scheme on textured quads so that the // lines show through glh.With(glh.Attrib{gl.ENABLE_BIT}, func() { gl.Disable(gl.LINE_SMOOTH) // vc.Draw(gl.LINES) vc.Render(gl.LINES) }) }) if block.tex != nil && (!detailed || block.vertex_data == nil) { border_color = [4]float64{0, 0, 1, 1} glh.With(glh.WindowCoords{Invert: true}, func() { gl.Color4f(1, 1, 1, 1) // Render textured block quad glh.With(block.tex, func() { glh.DrawQuadd(x1, y1, x2-x1, y2-y1) }) glh.With(glh.Primitive{gl.LINES}, func() { glh.Squared(x1, y1, x2-x1, y2-y1) }) }) if block.vertex_data != nil && !block.detail_needed { // TODO: figure out when we can unload // Hey, we can unload you, because you are not needed block.vertex_data = nil } } if detailed && block.vertex_data != nil { glh.With(glh.Matrix{gl.MODELVIEW}, func() { // TODO: A little less co-ordinate insanity? gl.Translated(0, -2, 0) gl.Scaled(1, 4/float64(*nback), 1) gl.Translated(0, -float64(start), 0) gl.PointSize(2) block.vertex_data.Render(gl.POINTS) }) } glh.With(glh.WindowCoords{Invert: true}, func() { // Block boundaries gl.Color4dv(&border_color) gl.LineWidth(1) glh.With(glh.Primitive{gl.LINE_LOOP}, func() { glh.Squared(x1, y1, x2-x1, y2-y1) }) }) }) }
func (r *RenderTarget) Render(verts []Vertex, primType PrimitiveType, states RenderStates) { // Nothing to draw? if len(verts) == 0 { return } // First set the persistent OpenGL states if it's the very first call if !r.glStatesSet { r.resetGlStates() } // Check if the vertex count is low enough so that we can pre-transform them // TODO: Fix vertex cache useVertexCache := /*len(verts) <= vertexCacheSize*/ false if useVertexCache { // Pre-transform the vertices and store them into the vertex cache for i := 0; i < len(verts); i++ { r.vertexCache[i].Pos = states.Transform.TransformPoint(verts[i].Pos) r.vertexCache[i].Color = verts[i].Color r.vertexCache[i].TexCoords = verts[i].TexCoords } // Since vertices are transformed, we must use an identity transform to render them if !r.useVertexCache { r.applyTransform(IdentityTransform()) } } else { r.applyTransform(states.Transform) } // Apply the view if r.viewChanged { r.applyCurrentView() } // Apply the blend mode if states.BlendMode != r.lastBlendMode { //r.applyBlendMode(states.BlendMode) } // Apply the texture var textureId uint64 if states.Texture != nil { textureId = states.Texture.cacheId } if textureId != r.lastTextureId { r.applyTexture(states.Texture) } // Apply the shader // TODO /*if states.shader { applyShader(states.shader); }*/ // If we pre-transform the vertices, we must use our internal vertex cache if useVertexCache { // ... and if we already used it previously, we don't need to set the pointers again if !r.useVertexCache { verts = r.vertexCache[:] } else { verts = nil } } // ######################################### if len(verts) > 0 { // Find the OpenGL primitive type modes := [...]gl.GLenum{gl.POINTS, gl.LINES, gl.LINE_STRIP, gl.TRIANGLES, gl.TRIANGLE_STRIP, gl.TRIANGLE_FAN, gl.QUADS} mode := modes[primType] gl.Begin(mode) for i, _ := range verts { gl.TexCoord2f(verts[i].TexCoords.X, verts[i].TexCoords.Y) gl.Color4f(verts[i].Color.R/255, verts[i].Color.G/255, verts[i].Color.B/255, verts[i].Color.A/255) gl.Vertex2f(verts[i].Pos.X, verts[i].Pos.Y) } gl.End() } // ######################################### // Setup the pointers to the vertices' components /*if len(verts) > 0 { vData := make([]Vector2, len(verts)) //cData := make([]byte, len(verts)) tData := make([]Vector2, len(verts)) for i, _ := range verts { vData[i] = verts[i].Pos //cData[i] = verts[i].Color tData[i] = verts[i].TexCoords } //const char* data = reinterpret_cast<const char*>(vertices); gl.VertexPointer(2, gl.FLOAT, 0, vData) //gl.ColorPointer(4, gl.UNSIGNED_BYTE, unsafe.Sizeof(Vertex), cData)) gl.TexCoordPointer(2, gl.FLOAT, 0, tData) } // Find the OpenGL primitive type modes := [...]gl.GLenum{gl.POINTS, gl.LINES, gl.LINE_STRIP, gl.TRIANGLES, gl.TRIANGLE_STRIP, gl.TRIANGLE_FAN, gl.QUADS} mode := modes[primType] // Draw the primitives gl.DrawArrays(mode, 0, len(verts))*/ // Unbind the shader, if any // TODO /*if (states.shader) { r.applyShader(nil) }*/ // Update the cache r.useVertexCache = useVertexCache }
func drawScene() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Translatef(0, 0, -3.0) gl.Rotatef(rotx, 1, 0, 0) gl.Rotatef(roty, 0, 1, 0) rotx += 0.5 roty += 0.5 texture.Bind(gl.TEXTURE_2D) gl.Color4f(1, 1, 1, 1) gl.Begin(gl.QUADS) gl.Normal3f(0, 0, 1) gl.TexCoord2f(0, 0) gl.Vertex3f(-1, -1, 1) gl.TexCoord2f(1, 0) gl.Vertex3f(1, -1, 1) gl.TexCoord2f(1, 1) gl.Vertex3f(1, 1, 1) gl.TexCoord2f(0, 1) gl.Vertex3f(-1, 1, 1) gl.Normal3f(0, 0, -1) gl.TexCoord2f(1, 0) gl.Vertex3f(-1, -1, -1) gl.TexCoord2f(1, 1) gl.Vertex3f(-1, 1, -1) gl.TexCoord2f(0, 1) gl.Vertex3f(1, 1, -1) gl.TexCoord2f(0, 0) gl.Vertex3f(1, -1, -1) gl.Normal3f(0, 1, 0) gl.TexCoord2f(0, 1) gl.Vertex3f(-1, 1, -1) gl.TexCoord2f(0, 0) gl.Vertex3f(-1, 1, 1) gl.TexCoord2f(1, 0) gl.Vertex3f(1, 1, 1) gl.TexCoord2f(1, 1) gl.Vertex3f(1, 1, -1) gl.Normal3f(0, -1, 0) gl.TexCoord2f(1, 1) gl.Vertex3f(-1, -1, -1) gl.TexCoord2f(0, 1) gl.Vertex3f(1, -1, -1) gl.TexCoord2f(0, 0) gl.Vertex3f(1, -1, 1) gl.TexCoord2f(1, 0) gl.Vertex3f(-1, -1, 1) gl.Normal3f(1, 0, 0) gl.TexCoord2f(1, 0) gl.Vertex3f(1, -1, -1) gl.TexCoord2f(1, 1) gl.Vertex3f(1, 1, -1) gl.TexCoord2f(0, 1) gl.Vertex3f(1, 1, 1) gl.TexCoord2f(0, 0) gl.Vertex3f(1, -1, 1) gl.Normal3f(-1, 0, 0) gl.TexCoord2f(0, 0) gl.Vertex3f(-1, -1, -1) gl.TexCoord2f(1, 0) gl.Vertex3f(-1, -1, 1) gl.TexCoord2f(1, 1) gl.Vertex3f(-1, 1, 1) gl.TexCoord2f(0, 1) gl.Vertex3f(-1, 1, -1) gl.End() }