func (c *Cube) AttachTextureFromBuffer(buffer []byte, width, height int) { gl.GenTextures(1, &c.textureBuffer) gl.BindTexture(gl.TEXTURE_2D, c.textureBuffer) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(width), gl.Sizei(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Void(&buffer[0])) }
// Screenshot takes a screenshot of the current window and return a // RGBA image.Image. func Screenshot(window mandala.Window) image.Image { width, height := window.GetSize() // Allocate the pixel buffer pixels := make([]byte, width*height*4) gl.PixelStorei(gl.PACK_ALIGNMENT, 1) // Read the framebuffer gl.ReadPixels(0, 0, gl.Sizei(width), gl.Sizei(height), gl.RGBA, gl.UNSIGNED_BYTE, gl.Void(&pixels[0])) // Create a RGBA image rect := image.Rect(0, 0, width, height) img := image.NewRGBA(rect) index := 0 for y := rect.Min.Y; y < rect.Max.Y; y++ { for x := rect.Min.X; x < rect.Max.X; x++ { color := color.RGBA{ pixels[index], pixels[index+1], pixels[index+2], pixels[index+3], } img.Set(x, rect.Max.Y-y, color) index += 4 } } return img }
func (renderState *renderState) init(window gorgasm.Window) { window.MakeContextCurrent() renderState.window = window width, height := window.GetSize() // Set the viewport gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) check() // Compile the shaders program := Program(FragmentShader(fsh), VertexShader(vsh)) gl.UseProgram(program) check() // Get attributes attrPos = uint32(gl.GetAttribLocation(program, "pos")) attrTexIn = uint32(gl.GetAttribLocation(program, "texIn")) unifTexture = gl.GetUniformLocation(program, "texture") gl.EnableVertexAttribArray(attrPos) gl.EnableVertexAttribArray(attrTexIn) check() // Upload vertices data gl.GenBuffers(1, &verticesArrayBuffer) gl.BindBuffer(gl.ARRAY_BUFFER, verticesArrayBuffer) gl.BufferData(gl.ARRAY_BUFFER, gl.SizeiPtr(len(vertices))*4, gl.Void(&vertices[0]), gl.STATIC_DRAW) check() // Upload texture data img, err := loadImage(GOPHER_PNG) if err != nil { panic(err) } // Prepare the image to be placed on a texture. bounds := img.Bounds() imgWidth, imgHeight := bounds.Size().X, bounds.Size().Y buffer := make([]byte, imgWidth*imgHeight*4) index := 0 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { r, g, b, a := img.At(x, y).RGBA() buffer[index] = byte(r) buffer[index+1] = byte(g) buffer[index+2] = byte(b) buffer[index+3] = byte(a) index += 4 } } gl.GenTextures(1, &textureBuffer) gl.BindTexture(gl.TEXTURE_2D, textureBuffer) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(imgWidth), gl.Sizei(imgHeight), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Void(&buffer[0])) check() gl.ClearColor(0.0, 0.0, 0.0, 1.0) }
func (w *World) Resize(width, height int) { w.Width, w.Height = width, height gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) w.projection = mathgl.Perspective(60, float32(width)/float32(height), 1, 20) w.projectionView = w.projection w.projectionView.Mul4(w.view) for _, obj := range w.objects { obj.projectionView = w.projectionView } }
func (renderState *renderState) init(window mandala.Window) { window.MakeContextCurrent() renderState.window = window width, height := window.GetSize() // Set the viewport gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) gl.ClearColor(0.0, 0.0, 1.0, 1.0) }
func (w *World) UploadRGBAImage(img *image.RGBA) gltext.Texture { t := new(texture) ib := img.Bounds() t.bounds = ib gl.GenTextures(1, &t.id) gl.BindTexture(gl.TEXTURE_2D, t.id) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(ib.Dx()), gl.Sizei(ib.Dy()), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Void(&img.Pix[0])) return t }
func (renderState *renderState) init(window mandala.Window) { window.MakeContextCurrent() renderState.window = window width, height := window.GetSize() // Set the viewport gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) check() // Compile the shaders program := shaders.NewProgram(fsh, vsh) program.Use() check() // Get attributes attrPos = program.GetAttribute("pos") attrTexIn = program.GetAttribute("texIn") unifTexture = program.GetUniform("texture") gl.EnableVertexAttribArray(attrPos) gl.EnableVertexAttribArray(attrTexIn) check() // Upload texture data img, err := loadImage(GOPHER_PNG) if err != nil { panic(err) } // Prepare the image to be placed on a texture. bounds := img.Bounds() imgWidth, imgHeight := bounds.Size().X, bounds.Size().Y buffer := make([]byte, imgWidth*imgHeight*4) index := 0 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { r, g, b, a := img.At(x, y).RGBA() buffer[index] = byte(r) buffer[index+1] = byte(g) buffer[index+2] = byte(b) buffer[index+3] = byte(a) index += 4 } } gl.GenTextures(1, &textureBuffer) gl.BindTexture(gl.TEXTURE_2D, textureBuffer) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(imgWidth), gl.Sizei(imgHeight), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Void(&buffer[0])) check() gl.ClearColor(0.0, 0.0, 0.0, 1.0) }
func NewWorld(width, height int) *World { gl.Enable(gl.DEPTH_TEST) gl.ClearColor(0.0, 0.0, 0.0, 0.0) gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) return &World{ Width: width, Height: height, objects: make([]*Cube, 0), projection: mathgl.Perspective(60, float32(width)/float32(height), 1, 20), view: mathgl.Ident4f(), } }
func (renderState *renderState) init(window mandala.Window) { window.MakeContextCurrent() renderState.window = window width, height := window.GetSize() // Set the viewport gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) gl.ClearColor(0.0, 0.0, 0.0, 1.0) renderState.boxProgram = shaders.NewProgram(shapes.DefaultBoxFS, shapes.DefaultBoxVS) renderState.segmentProgram = shaders.NewProgram(shapes.DefaultSegmentFS, shapes.DefaultSegmentVS) }
// Run runs renderLoop. The loop renders a frame and swaps the buffer // at each tick received. func renderLoopFunc(control *renderLoopControl) loop.LoopFunc { return func(loop loop.Loop) error { var state *gameState // Lock/unlock the loop to the current OS thread. This is // necessary because OpenGL functions should be called from // the same thread. runtime.LockOSThread() defer runtime.UnlockOSThread() // Create an instance of ticker and immediately stop // it because we don't want to swap buffers before // initializing a rendering state. ticker := time.NewTicker(time.Duration(1e9 / int(FramesPerSecond))) ticker.Stop() for { select { case window := <-control.window: ticker.Stop() state = newGameState(window) width, height := window.GetSize() gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) ticker = time.NewTicker(time.Duration(time.Second / time.Duration(FramesPerSecond))) case tap := <-control.tapEvent: state.world.explosion(tap[0], tap[1]) // At each tick render a frame and swap buffers. case <-ticker.C: state.draw() state.window.SwapBuffers() case event := <-control.pause: ticker.Stop() state.world.destroy() event.Paused <- true case <-control.resume: case <-loop.ShallStop(): ticker.Stop() return nil } } } }
// Run runs renderLoop. The loop renders a frame and swaps the buffer // at each tick received. func renderLoopFunc(control *renderLoopControl) loop.LoopFunc { return func(loop loop.Loop) error { var window mandala.Window // Lock/unlock the loop to the current OS thread. This is // necessary because OpenGL functions should be called from // the same thread. runtime.LockOSThread() defer runtime.UnlockOSThread() // Create an instance of ticker and immediately stop // it because we don't want to swap buffers before // initializing a rendering state. ticker := time.NewTicker(time.Duration(1e9 / int(FRAMES_PER_SECOND))) ticker.Stop() for { select { case window = <-control.window: ticker.Stop() window.MakeContextCurrent() width, height := window.GetSize() gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) mandala.Logf("Restarting rendering loop...") ticker = time.NewTicker(time.Duration(1e9 / int(FRAMES_PER_SECOND))) // At each tick render a frame and swap buffers. case <-ticker.C: draw() window.SwapBuffers() case event := <-control.pause: ticker.Stop() event.Paused <- true case <-control.resume: case <-loop.ShallStop(): ticker.Stop() return nil } } } }
func checkProgramLinkStatus(pid uint32) { var stat int32 gl.GetProgramiv(pid, gl.LINK_STATUS, &stat) if stat == 0 { var length int32 gl.GetProgramiv(pid, gl.INFO_LOG_LENGTH, &length) infoLog := gl.GetProgramInfoLog(pid, gl.Sizei(length), nil) log.Fatalf("Link error in program %d: \"%s\"\n", pid, infoLog[:len(infoLog)-1]) } }
func checkShaderCompileStatus(shader uint32) { var stat int32 gl.GetShaderiv(shader, gl.COMPILE_STATUS, &stat) if stat == 0 { var length int32 gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &length) infoLog := gl.GetShaderInfoLog(shader, gl.Sizei(length), nil) log.Fatalf("Compile error in shader %d: \"%s\"\n", shader, infoLog[:len(infoLog)-1]) } }
func (w *world) addImageAsTexture(filename string) uint32 { var texBuffer uint32 texImg, err := loadImageResource(filename) if err != nil { panic(err) } b := texImg.Bounds() rgbaImage := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy())) draw.Draw(rgbaImage, rgbaImage.Bounds(), texImg, b.Min, draw.Src) width, height := gl.Sizei(b.Dx()), gl.Sizei(b.Dy()) gl.GenTextures(1, &texBuffer) gl.BindTexture(gl.TEXTURE_2D, texBuffer) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Void(&rgbaImage.Pix[0])) return texBuffer }
func (c *Cube) AttachTexture(img image.Image) { bounds := img.Bounds() width, height := bounds.Size().X, bounds.Size().Y buffer := make([]byte, width*height*4) index := 0 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { r, g, b, a := img.At(x, y).RGBA() buffer[index] = byte(r) buffer[index+1] = byte(g) buffer[index+2] = byte(b) buffer[index+3] = byte(a) index += 4 } } gl.GenTextures(1, &c.textureBuffer) gl.BindTexture(gl.TEXTURE_2D, c.textureBuffer) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(width), gl.Sizei(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Void(&buffer[0])) }
func (c *Cube) Draw() { c.Program.Use() gl.VertexAttribPointer(c.attrPos, 4, gl.FLOAT, false, SizeOfFloat*6, &c.Vertices[0]) gl.VertexAttribPointer(c.attrTexIn, 2, gl.FLOAT, false, 6*SizeOfFloat, &c.Vertices[4]) gl.UniformMatrix4fv(int32(c.uniformModel), 1, false, (*float32)(&c.model[0])) gl.UniformMatrix4fv(int32(c.uniformProjectionView), 1, false, (*float32)(&c.projectionView[0])) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, c.textureBuffer) gl.Uniform1i(int32(c.uniformTexture), 0) gl.DrawElements(gl.TRIANGLES, gl.Sizei(len(c.indices)), gl.UNSIGNED_BYTE, gl.Void(&c.indices[0])) gl.Flush() gl.Finish() }