func (vb *VertexBuffer) Render(position Point3) { gl.PushMatrix() gl.Translated( gl.Double(position.X), gl.Double(position.Y), gl.Double(position.Z)) gl.VertexPointer( gl.Int(3), gl.DOUBLE, 0, gl.Pointer(&vb.VertexData[0])) gl.ColorPointer( gl.Int(4), gl.DOUBLE, 0, gl.Pointer(&vb.ColorData[0])) gl.TexCoordPointer( gl.Int(2), gl.DOUBLE, 0, gl.Pointer(&vb.TexCoordData[0])) for i := range vb.RenderSteps { rs := &vb.RenderSteps[i] gl.DrawElements( rs.Mode, gl.Sizei(len(rs.Indices)), gl.UNSIGNED_INT, gl.Pointer(&rs.Indices[0])) } gl.PopMatrix() }
func (ms *ManaSource) Draw(local *LocalData, zoom float64, dx float64, dy float64) { if local.nodeTextureData == nil { // gl.Enable(gl.TEXTURE_2D) local.nodeTextureData = make([]byte, ms.options.NumNodeRows*ms.options.NumNodeCols*3) gl.GenTextures(1, &local.nodeTextureId) gl.BindTexture(gl.TEXTURE_2D, local.nodeTextureId) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGB, gl.Sizei(ms.options.NumNodeRows), gl.Sizei(ms.options.NumNodeCols), 0, gl.RGB, gl.UNSIGNED_BYTE, gl.Pointer(&local.nodeTextureData[0])) } for i := range ms.rawNodes { for c := 0; c < 3; c++ { color_frac := ms.rawNodes[i].Mana[c] * 1.0 / ms.options.NodeMagnitude color_range := float64(ms.options.MaxNodeBrightness - ms.options.MinNodeBrightness) local.nodeTextureData[i*3+c] = byte( color_frac*color_range + float64(ms.options.MinNodeBrightness)) } } gl.Enable(gl.TEXTURE_2D) //gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, local.nodeTextureId) gl.TexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, gl.Sizei(ms.options.NumNodeRows), gl.Sizei(ms.options.NumNodeCols), gl.RGB, gl.UNSIGNED_BYTE, gl.Pointer(&local.nodeTextureData[0])) base.EnableShader("nodes") base.SetUniformI("nodes", "width", ms.options.NumNodeRows*3) base.SetUniformI("nodes", "height", ms.options.NumNodeCols*3) base.SetUniformI("nodes", "drains", 1) base.SetUniformI("nodes", "tex0", 0) base.SetUniformI("nodes", "tex1", 1) base.SetUniformF("nodes", "zoom", float32(zoom)) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, local.nodeTextureId) // I have no idea why this value for move works, but it does. So, hooray. move := (dx - dy) / 2 texture.RenderAdvanced(move, -move, dy, dx, 3.1415926535/2, true) base.EnableShader("") gl.Disable(gl.TEXTURE_2D) }
// NewSprite creates a new Sprite object using the given data, which is // expected to be in RGBA format. If you use PNG image files, you can use the // NewSpriteFromImage shortcut function instead. func NewSprite(x, y, width, height float64, data []byte, clip int) (*Sprite, error) { verticies := []float64{ x, y, x + width, y, x, y + height, x + width, y + height, x + width, y, x, y + height} shape, err := NewShape(gl.TRIANGLES, verticies) if err != nil { return nil, err } sprite := &Sprite{texcoordBuffer: 0, texture: nil, shape: shape} texCoords := []float32{ 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1} gl.GenBuffers(1, &sprite.texcoordBuffer) gl.BindBuffer(gl.ARRAY_BUFFER, gl.Uint(sprite.texcoordBuffer)) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(len(texCoords)*4), gl.Pointer(&texCoords[0]), gl.STREAM_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) sprite.texture = make([]gl.Uint, clip) gl.GenTextures(gl.Sizei(clip), &sprite.texture[0]) clips := make([][]byte, clip) for i := range clips { clips[i] = data[i*(len(data)/len(clips)) : (i+1)*(len(data)/len(clips))] gl.BindTexture(gl.TEXTURE_2D, sprite.texture[len(clips)-1-i]) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(width), gl.Sizei(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&clips[i][0])) } gl.BindTexture(gl.TEXTURE_2D, 0) return sprite, checkForErrors() }
func (m *Model) draw() { m.shader.use() gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, m.texture_id) gl.Uniform1i(m.shader.uniform_texture, 0) //texcoord if m.has_uv { gl.BindBuffer(gl.ARRAY_BUFFER, m.texcoord) gl.EnableVertexAttribArray(m.shader.attribute_texcoord) gl.VertexAttribPointer( m.shader.attribute_texcoord, 2, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil)) } gl.BindBuffer(gl.ARRAY_BUFFER, m.buffer) gl.EnableVertexAttribArray(m.shader.attribute_vertex) gl.VertexAttribPointer( m.shader.attribute_vertex, 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil)) gl.BindBuffer(gl.ARRAY_BUFFER, m.normal_buf) gl.EnableVertexAttribArray(m.shader.attribute_normal) gl.VertexAttribPointer( m.shader.attribute_normal, 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil)) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, m.index) gl.DrawElements(gl.TRIANGLES, gl.Sizei(len(m.indices)), gl.UNSIGNED_INT, gl.Pointer(nil)) gl.BindBuffer(gl.ARRAY_BUFFER, 0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0) gl.DisableVertexAttribArray(m.shader.attribute_vertex) gl.DisableVertexAttribArray(m.shader.attribute_normal) if m.has_uv { gl.DisableVertexAttribArray(m.shader.attribute_texcoord) } }
func initquad() { ver := []gl.Float{-1, 1, 1, 1, -1, -1, 1, -1} gl.BindBuffer(gl.ARRAY_BUFFER, 1) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(ver)), gl.Pointer(&ver[0]), gl.STATIC_DRAW) gl.VertexPointer(2, gl.FLOAT, 0, nil) tex := []gl.Float{0, 0, 1, 0, 0, 1, 1, 1} gl.BindBuffer(gl.ARRAY_BUFFER, 2) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4*len(tex)), gl.Pointer(&tex[0]), gl.STATIC_DRAW) gl.TexCoordPointer(2, gl.FLOAT, 0, nil) gl.EnableClientState(gl.VERTEX_ARRAY) gl.EnableClientState(gl.TEXTURE_COORD_ARRAY) }
/* Uses the image library to turn a PNG into a gl texture */ func createTexture(r io.Reader) (textureId gl.Uint, err error) { img, err := png.Decode(r) if err != nil { return 0, err } rgbaImg, ok := img.(*image.RGBA) if !ok { return 0, errors.New("texture must be an RGBA image") } gl.GenTextures(1, &textureId) gl.BindTexture(gl.TEXTURE_2D, textureId) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) // flip image: first pixel is lower left corner imgWidth, imgHeight := img.Bounds().Dx(), img.Bounds().Dy() data := make([]byte, imgWidth*imgHeight*4) lineLen := imgWidth * 4 dest := len(data) - lineLen for src := 0; src < len(rgbaImg.Pix); src += rgbaImg.Stride { copy(data[dest:dest+lineLen], rgbaImg.Pix[src:src+rgbaImg.Stride]) dest -= lineLen } gl.TexImage2D(gl.TEXTURE_2D, 0, 4, gl.Sizei(imgWidth), gl.Sizei(imgHeight), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&data[0])) return textureId, nil }
// Move moves the Shape object a specified distance. func (shape *Shape) Move(x, y float64) { var verticies []float32 for i := 0; i < len(shape.verticies); i += 2 { shape.verticies[i] += float32(x) shape.verticies[i+1] += float32(y) } if shape.scaleX != 1 || shape.scaleY != 1 { verticies = make([]float32, len(shape.verticies)) xTransform := shape.verticies[0] - (shape.verticies[0] * float32(shape.scaleX)) yTransform := shape.verticies[1] - (shape.verticies[1] * float32(shape.scaleY)) for i := range verticies { if i%2 == 0 { verticies[i] = shape.verticies[i] * float32(shape.scaleX) verticies[i] += xTransform } else { verticies[i] = shape.verticies[i] * float32(shape.scaleY) verticies[i] += yTransform } } } else { verticies = shape.verticies } gl.BindBuffer(gl.ARRAY_BUFFER, shape.vertexBuffer) gl.BufferSubData(gl.ARRAY_BUFFER, 0, gl.Sizeiptr(len(verticies)*4), gl.Pointer(&verticies[0])) gl.BindBuffer(gl.ARRAY_BUFFER, 0) }
func loadCubeToGPU() { newNormal(0, 0, 1) newVertex(-1, -1, 1) newVertex(1, -1, 1) newVertex(1, 1, 1) newVertex(-1, 1, 1) newNormal(0, 0, -1) newVertex(-1, -1, -1) newVertex(-1, 1, -1) newVertex(1, 1, -1) newVertex(1, -1, -1) newNormal(0, 1, 0) newVertex(-1, 1, -1) newVertex(-1, 1, 1) newVertex(1, 1, 1) newVertex(1, 1, -1) newNormal(0, -1, 0) newVertex(-1, -1, -1) newVertex(1, -1, -1) newVertex(1, -1, 1) newVertex(-1, -1, 1) newNormal(1, 0, 0) newVertex(1, -1, -1) newVertex(1, 1, -1) newVertex(1, 1, 1) newVertex(1, -1, 1) newNormal(-1, 0, 0) newVertex(-1, -1, -1) newVertex(-1, -1, 1) newVertex(-1, 1, 1) newVertex(-1, 1, -1) gl.GenBuffers(1, &gVBO) gl.BindBuffer(gl.ARRAY_BUFFER, gVBO) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(unsafe.Sizeof(Vertex{})*24), gl.Pointer(&Vertices[0]), gl.STATIC_DRAW) gl.EnableClientState(gl.VERTEX_ARRAY) gl.EnableClientState(gl.NORMAL_ARRAY) gl.VertexPointer(3, gl.FLOAT, 24, nil) tmpStruct := Vertex{} gl.NormalPointer(gl.FLOAT, gl.Sizei(unsafe.Sizeof(Vertex{})), gl.Pointer(unsafe.Offsetof(tmpStruct.normal))) }
func upload(id gl.Uint, data []byte, stride int, w int, h int) { gl.BindTexture(gl.TEXTURE_2D, id) gl.PixelStorei(gl.UNPACK_ROW_LENGTH, gl.Int(stride)) gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.Sizei(w), gl.Sizei(h), 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, gl.Pointer(&data[0])) }
func (m *Model) init() (err error) { m.shader.init("shader/simple.vert", "shader/simple.frag") /* gl.GenBuffers(1, &m.buffer) gl.BindBuffer(gl.ARRAY_BUFFER, m.buffer); gl.BufferData( gl.ARRAY_BUFFER, gl.Sizeiptr(len(m.vertices)* int(unsafe.Sizeof(m.vertices[0]))), gl.Pointer(&m.vertices[0]), gl.STATIC_DRAW); */ m.initBufferFloat(&m.buffer, gl.ARRAY_BUFFER, &m.vertices) gl.GenBuffers(1, &m.index) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, m.index) gl.BufferData( gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(len(m.indices)*int(unsafe.Sizeof(m.indices[0]))), gl.Pointer(&m.indices[0]), gl.STATIC_DRAW) gl.GenBuffers(1, &m.normal_buf) gl.BindBuffer(gl.ARRAY_BUFFER, m.normal_buf) gl.BufferData( gl.ARRAY_BUFFER, gl.Sizeiptr(len(m.normals)*int(unsafe.Sizeof(m.normals[0]))), gl.Pointer(&m.normals[0]), gl.STATIC_DRAW) m.initTexture() if m.has_uv { gl.GenBuffers(1, &m.texcoord) gl.BindBuffer(gl.ARRAY_BUFFER, m.texcoord) gl.BufferData( gl.ARRAY_BUFFER, gl.Sizeiptr(len(m.uvs)*int(unsafe.Sizeof(m.uvs[0]))), gl.Pointer(&m.uvs[0]), gl.STATIC_DRAW) } return }
func (m *Model) initBufferFloat(buffer *gl.Uint, t gl.Enum, data *[]gl.Float) { gl.GenBuffers(1, buffer) gl.BindBuffer(t, *buffer) gl.BufferData( t, gl.Sizeiptr(len(*data)*int(unsafe.Sizeof((*data)[0]))), gl.Pointer(&(*data)[0]), gl.STATIC_DRAW) }
func glInit(width, height int) { gl.Init() gl.Enable(gl.TEXTURE_2D) gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) gl.Viewport(0, 0, gl.Sizei(width), gl.Sizei(height)) gl.MatrixMode(gl.PROJECTION) gl.LoadIdentity() gl.Ortho(0, gl.Double(width), gl.Double(height), 0, -1, 1) gl.MatrixMode(gl.MODELVIEW) gl.LoadIdentity() gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.EnableClientState(gl.VERTEX_ARRAY) gl.EnableClientState(gl.COLOR_ARRAY) gl.EnableClientState(gl.TEXTURE_COORD_ARRAY) gl.VertexPointer(2, gl.FLOAT, 0, gl.Pointer(&vs[0])) gl.ColorPointer(3, gl.UNSIGNED_BYTE, 0, gl.Pointer(&cs[0])) gl.TexCoordPointer(2, gl.FLOAT, 0, gl.Pointer(&ts[0])) }
func makeErrorTexture() { gl.Enable(gl.TEXTURE_2D) gl.GenTextures(1, (*gl.Uint)(&error_texture)) gl.BindTexture(gl.TEXTURE_2D, error_texture) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) pink := []byte{255, 0, 255, 255} gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.BYTE, gl.Pointer(&pink[0])) }
func reuploadTexture(tex *gl.Uint, w, h int, data []byte) { if *tex > 0 { gl.BindTexture(gl.TEXTURE_2D, *tex) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(w), gl.Sizei(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&data[0])) if gl.GetError() != gl.NO_ERROR { gl.DeleteTextures(1, tex) panic("Failed to reupload texture") } return } *tex = uploadTexture_RGBA32(w, h, data) }
// NewShapeFromShape creates a copy of an existing Shape object. func NewShapeFromShape(copyShape *Shape) (*Shape, error) { shape := &Shape{mode: copyShape.mode, size: copyShape.size, verticies: make([]float32, len(copyShape.verticies)), scaleX: copyShape.scaleX, scaleY: copyShape.scaleY} copy(shape.verticies, copyShape.verticies) gl.GenBuffers(1, &shape.vertexBuffer) gl.BindBuffer(gl.ARRAY_BUFFER, shape.vertexBuffer) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(len(shape.verticies)*4), gl.Pointer(&shape.verticies[0]), gl.DYNAMIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) return shape, checkForErrors() }
func screenShot() { b := make([]uint8, Width*Height*4) gl.ReadPixels(0, 0, Width, Height, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&b[0])) rect := image.Rect(0, 0, Width, Height) im := image.NRGBA{ Pix: b, Stride: Width * 4, Rect: rect, } if f, err := os.Create("screenshot.png"); err == nil { defer f.Close() png.Encode(f, &im) } }
// NewShape creates a new Shape object based on the verticies and shape type. func NewShape(shapeType ShapeType, verticies []float64) (*Shape, error) { verticies32 := make([]float32, len(verticies)) for i, val := range verticies { verticies32[i] = float32(val) } shape := &Shape{mode: gl.Enum(shapeType), size: len(verticies), vertexBuffer: 0, verticies: verticies32, scaleX: 1, scaleY: 1} gl.GenBuffers(1, &shape.vertexBuffer) gl.BindBuffer(gl.ARRAY_BUFFER, gl.Uint(shape.vertexBuffer)) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(shape.size*4), gl.Pointer(&shape.verticies[0]), gl.DYNAMIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) return shape, checkForErrors() }
func (m *Model) initTexture() { //file, err := os.Open("model/test.png") file, err := os.Open("model/ceil.png") if err != nil { log.Fatal(err) } defer file.Close() img, _, err := image.Decode(file) if err != nil { log.Fatal(err) } rgbaImg, ok := img.(*image.NRGBA) if !ok { //return 0, errors.New("texture must be an NRGBA image") log.Fatal("image is not rgba") } gl.GenTextures(1, &m.texture_id) gl.BindTexture(gl.TEXTURE_2D, m.texture_id) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) // flip image: first pixel is lower left corner img_width, img_height := img.Bounds().Dx(), img.Bounds().Dy() data := make([]byte, img_width*img_height*4) line_len := img_width * 4 dest := len(data) - line_len for src := 0; src < len(rgbaImg.Pix); src += rgbaImg.Stride { copy(data[dest:dest+line_len], rgbaImg.Pix[src:src+rgbaImg.Stride]) dest -= line_len } gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, //4, gl.Sizei(img_width), gl.Sizei(img_height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&data[0])) }
func uploadTexture_RGBA32(w, h int, data []byte) gl.Uint { var id gl.Uint gl.GenTextures(1, &id) gl.BindTexture(gl.TEXTURE_2D, id) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(w), gl.Sizei(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&data[0])) if gl.GetError() != gl.NO_ERROR { gl.DeleteTextures(1, &id) panic("Failed to load a texture") } return id }
func (m *Manager) LoadSprite(path string) (*Sprite, error) { // We can't run this during an init() function because it will get queued to // run before the opengl context is created, so we just check here and run // it if we haven't run it before. gen_tex_once.Do(func() { render.Queue(func() { gl.Enable(gl.TEXTURE_2D) gl.GenTextures(1, &error_texture) gl.BindTexture(gl.TEXTURE_2D, error_texture) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) pink := []byte{255, 0, 255, 255} gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_INT, gl.Pointer(&pink[0])) }) }) path = filepath.Clean(path) err := m.loadSharedSprite(path) if err != nil { return nil, err } var s Sprite m.mutex.Lock() s.shared = m.shared[path] m.mutex.Unlock() s.anim_node = s.shared.anim_start s.state_node = s.shared.state_start return &s, nil }
// Sets up anything that wouldn't have been loaded from disk, including // all opengl data, and sets up finalizers for that data. func (d *Dictionary) setupGlStuff() { d.dlists = make(map[string]uint32) d.strs = make(map[string]strBuffer) d.pars = make(map[string]strBuffer) // TODO: This finalizer is untested runtime.SetFinalizer(d, func(d *Dictionary) { render.Queue(func() { for _, v := range d.dlists { gl.DeleteLists(gl.Uint(v), 1) } }) }) render.Queue(func() { gl.Enable(gl.TEXTURE_2D) gl.GenTextures(1, (*gl.Uint)(&d.texture)) gl.BindTexture(gl.TEXTURE_2D, gl.Uint(d.texture)) gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.ALPHA, gl.Sizei(d.data.Dx), gl.Sizei(d.data.Dy), 0, gl.ALPHA, gl.UNSIGNED_BYTE, gl.Pointer(&d.data.Pix[0])) gl.Disable(gl.TEXTURE_2D) }) }
func (s *sheet) makeTexture(pixer <-chan []byte) { gl.Enable(gl.TEXTURE_2D) gl.GenTextures(1, &s.texture) gl.BindTexture(gl.TEXTURE_2D, s.texture) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) data := <-pixer gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(s.dx), gl.Sizei(s.dy), 0, gl.RGBA, gl.UNSIGNED_INT, gl.Pointer(&data[0])) memory.FreeBlock(data) }
// SetScaling sets the scaling factor of the Shape object. For instance, an x // and y scale value of two will make the Shape object twice as large. func (shape *Shape) SetScaling(scaleX, scaleY float64) { shape.scaleX = scaleX shape.scaleY = scaleY verticies := make([]float32, len(shape.verticies)) xTransform := shape.verticies[0] - (shape.verticies[0] * float32(scaleX)) yTransform := shape.verticies[1] - (shape.verticies[1] * float32(scaleY)) for i := range verticies { if i%2 == 0 { verticies[i] = shape.verticies[i] * float32(scaleX) verticies[i] += xTransform } else { verticies[i] = shape.verticies[i] * float32(scaleY) verticies[i] += yTransform } } gl.BindBuffer(gl.ARRAY_BUFFER, shape.vertexBuffer) gl.BufferSubData(gl.ARRAY_BUFFER, 0, gl.Sizeiptr(len(verticies)*4), gl.Pointer(&verticies[0])) gl.BindBuffer(gl.ARRAY_BUFFER, 0) }
func (w *glfwBackend) Open(width, height, zoom int, fs bool, font *FontData) { if err := glfw.Init(); err != nil { panic(err) } w.font = font w.zoom = zoom w.width = width w.height = height var fwidth = width * font.CellWidth * zoom var fheight = height * font.CellHeight * zoom var twidth = fwidth var theight = fheight flag := glfw.Windowed if fs { flag = glfw.Fullscreen dm := glfw.DesktopMode() twidth = dm.W theight = dm.H } glfw.OpenWindowHint(glfw.WindowNoResize, gl.TRUE) err := glfw.OpenWindow(twidth, theight, 8, 8, 8, 8, 0, 0, flag) if err != nil { panic(err) } w.key = NOKEY glfw.SetWindowCloseCallback(func() int { w.Close(); return 0 }) glfw.SetKeyCallback(func(key, state int) { w.setKey(key, state) }) glfw.SetCharCallback(func(key, state int) { w.setKey(key, state) }) glfw.Enable(glfw.KeyRepeat) w.mouse = new(MouseData) glfw.Enable(glfw.MouseCursor) glfw.SetMousePosCallback(func(x, y int) { w.mouseMove(x, y) }) glfw.SetMouseButtonCallback(func(but, state int) { w.mousePress(but, state) }) glfw.Enable(glfw.MouseCursor) xoff := float32(twidth-fwidth) / 2.0 yoff := float32(theight-fheight) / 2.0 fc := float32(font.CellWidth * zoom) fch := float32(font.CellHeight * zoom) for y := 0; y < height; y++ { for x := 0; x < width; x++ { cx := xoff + float32(x)*fc cy := yoff + float32(y)*fch w.verts = append(w.verts, cx, cy, cx, cy+fch, cx+fc, cy+fch, cx+fc, cy) } } runtime.LockOSThread() glInit(twidth, theight) m := font.Image.(*image.RGBA) w.s = float32(font.CellWidth) / float32(m.Bounds().Max.X) w.t = float32(font.CellHeight) / float32(m.Bounds().Max.Y) textures = make([]gl.Uint, 2) gl.GenTextures(2, &textures[0]) gl.BindTexture(gl.TEXTURE_2D, textures[0]) 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(m.Bounds().Max.X), gl.Sizei(m.Bounds().Max.Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&m.Pix[0])) m = image.NewRGBA(image.Rect(0, 0, font.CellWidth, font.CellHeight)) draw.Draw(m, m.Bounds(), &image.Uniform{White}, image.ZP, draw.Src) gl.BindTexture(gl.TEXTURE_2D, textures[1]) 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(m.Bounds().Max.X), gl.Sizei(m.Bounds().Max.Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&m.Pix[0])) w.open = true }
func Screenshot() { log.Println("screenshot") img := image.NewNRGBA(image.Rect(0, 0, Width, Height)) gl.ReadPixels(0, 0, gl.Sizei(Width), gl.Sizei(Height), gl.RGBA, gl.UNSIGNED_INT_8_8_8_8, gl.Pointer(&img.Pix[0])) // reverse byte order, opengl seems to use little endian. pix := img.Pix for i := 0; i < len(pix); i += 4 { pix[i+0], pix[i+1], pix[i+2], pix[i+3] = pix[i+3], pix[i+2], pix[i+1], pix[i+0] } fname := fmt.Sprintf("frame%04d.png", scroti) scroti++ f, err := os.OpenFile(fname, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666) core.Fatal(err) defer f.Close() core.Fatal(png.Encode(f, img)) }
// Need floor, right wall, and left wall matrices to draw the details func (room *Room) render(floor, left, right mathgl.Mat4, zoom float32, base_alpha byte, drawables []Drawable, los_tex *LosTexture, floor_drawers []FloorDrawer) { do_color := func(r, g, b, a byte) { R, G, B, A := room.Color() A = alphaMult(A, base_alpha) gl.Color4ub(alphaMult(R, r), alphaMult(G, g), alphaMult(B, b), alphaMult(A, a)) } gl.Enable(gl.TEXTURE_2D) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.Enable(gl.STENCIL_TEST) gl.ClearStencil(0) gl.Clear(gl.STENCIL_BUFFER_BIT) gl.EnableClientState(gl.VERTEX_ARRAY) gl.EnableClientState(gl.TEXTURE_COORD_ARRAY) defer gl.DisableClientState(gl.VERTEX_ARRAY) defer gl.DisableClientState(gl.TEXTURE_COORD_ARRAY) var vert roomVertex planes := []plane{ {room.left_buffer, room.Wall, &left}, {room.right_buffer, room.Wall, &right}, {room.floor_buffer, room.Floor, &floor}, } gl.PushMatrix() defer gl.PopMatrix() if los_tex != nil { gl.LoadMatrixf(&floor[0]) gl.ClientActiveTexture(gl.TEXTURE1) gl.ActiveTexture(gl.TEXTURE1) gl.Enable(gl.TEXTURE_2D) gl.EnableClientState(gl.TEXTURE_COORD_ARRAY) los_tex.Bind() gl.BindBuffer(gl.ARRAY_BUFFER, room.vbuffer) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u))) gl.ClientActiveTexture(gl.TEXTURE0) gl.ActiveTexture(gl.TEXTURE0) base.EnableShader("los") base.SetUniformI("los", "tex2", 1) } var mul, run mathgl.Mat4 for _, plane := range planes { gl.LoadMatrixf(&floor[0]) run.Assign(&floor) // Render the doors and cut out the stencil buffer so we leave them empty // if they're open switch plane.mat { case &left: gl.StencilFunc(gl.ALWAYS, 1, 1) gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) for _, door := range room.Doors { if door.Facing != FarLeft { continue } door.TextureData().Bind() R, G, B, A := door.Color() do_color(R, G, B, alphaMult(A, room.far_left.wall_alpha)) gl.ClientActiveTexture(gl.TEXTURE0) door.TextureData().Bind() if door.door_glids.floor_buffer != 0 { gl.BindBuffer(gl.ARRAY_BUFFER, door.threshold_glids.vbuffer) gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x))) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, door.door_glids.floor_buffer) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u))) gl.ClientActiveTexture(gl.TEXTURE1) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u))) gl.DrawElements(gl.TRIANGLES, door.door_glids.floor_count, gl.UNSIGNED_SHORT, nil) } } gl.StencilFunc(gl.NOTEQUAL, 1, 1) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) do_color(255, 255, 255, room.far_left.wall_alpha) case &right: gl.StencilFunc(gl.ALWAYS, 1, 1) gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) for _, door := range room.Doors { if door.Facing != FarRight { continue } door.TextureData().Bind() R, G, B, A := door.Color() do_color(R, G, B, alphaMult(A, room.far_right.wall_alpha)) gl.ClientActiveTexture(gl.TEXTURE0) door.TextureData().Bind() if door.door_glids.floor_buffer != 0 { gl.BindBuffer(gl.ARRAY_BUFFER, door.threshold_glids.vbuffer) gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x))) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, door.door_glids.floor_buffer) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u))) gl.ClientActiveTexture(gl.TEXTURE1) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u))) gl.DrawElements(gl.TRIANGLES, door.door_glids.floor_count, gl.UNSIGNED_SHORT, nil) } } gl.StencilFunc(gl.NOTEQUAL, 1, 1) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) do_color(255, 255, 255, room.far_right.wall_alpha) case &floor: gl.StencilFunc(gl.ALWAYS, 2, 2) gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) do_color(255, 255, 255, 255) } gl.ClientActiveTexture(gl.TEXTURE0) gl.BindBuffer(gl.ARRAY_BUFFER, room.vbuffer) gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x))) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u))) gl.ClientActiveTexture(gl.TEXTURE1) if los_tex != nil { los_tex.Bind() } gl.BindBuffer(gl.ARRAY_BUFFER, room.vbuffer) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u))) // Now draw the walls gl.LoadMatrixf(&floor[0]) plane.texture.Data().Bind() gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, plane.index_buffer) if (plane.mat == &left || plane.mat == &right) && strings.Contains(string(room.Wall.Path), "gradient.png") { base.EnableShader("gorey") base.SetUniformI("gorey", "tex", 0) base.SetUniformI("gorey", "foo", Foo) base.SetUniformF("gorey", "num_rows", Num_rows) base.SetUniformF("gorey", "noise_rate", Noise_rate) base.SetUniformF("gorey", "num_steps", Num_steps) } if plane.mat == &floor && strings.Contains(string(room.Floor.Path), "gradient.png") { base.EnableShader("gorey") base.SetUniformI("gorey", "tex", 0) base.SetUniformI("gorey", "foo", Foo) base.SetUniformF("gorey", "num_rows", Num_rows) base.SetUniformF("gorey", "noise_rate", Noise_rate) base.SetUniformF("gorey", "num_steps", Num_steps) zexp := math.Log(float64(zoom)) frac := 1 - 1/zexp frac = (frac - 0.6) * 5.0 switch { case frac > 0.7: base.SetUniformI("gorey", "range", 1) case frac > 0.3: base.SetUniformI("gorey", "range", 2) default: base.SetUniformI("gorey", "range", 3) } } if plane.mat == &floor { R, G, B, _ := room.Color() gl.Color4ub(R, G, B, 255) } gl.DrawElements(gl.TRIANGLES, gl.Sizei(room.floor_count), gl.UNSIGNED_SHORT, nil) if los_tex != nil { base.EnableShader("los") } else { base.EnableShader("") } } for _, wt := range room.WallTextures { if room.wall_texture_gl_map == nil { room.wall_texture_gl_map = make(map[*WallTexture]wallTextureGlIds) room.wall_texture_state_map = make(map[*WallTexture]wallTextureState) } ids := room.wall_texture_gl_map[wt] state := room.wall_texture_state_map[wt] var new_state wallTextureState new_state.flip = wt.Flip new_state.rot = wt.Rot new_state.x = wt.X new_state.y = wt.Y new_state.room.x = room.X new_state.room.y = room.Y new_state.room.dx = room.Size.Dx new_state.room.dy = room.Size.Dy if new_state != state { wt.setupGlStuff(room.X, room.Y, room.Size.Dx, room.Size.Dy, &ids) room.wall_texture_gl_map[wt] = ids room.wall_texture_state_map[wt] = new_state } gl.LoadMatrixf(&floor[0]) if ids.vbuffer != 0 { wt.Texture.Data().Bind() R, G, B, A := wt.Color() gl.ClientActiveTexture(gl.TEXTURE0) gl.BindBuffer(gl.ARRAY_BUFFER, ids.vbuffer) gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x))) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u))) gl.ClientActiveTexture(gl.TEXTURE1) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u))) gl.ClientActiveTexture(gl.TEXTURE0) if ids.floor_buffer != 0 { gl.StencilFunc(gl.ALWAYS, 2, 2) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ids.floor_buffer) gl.Color4ub(R, G, B, A) gl.DrawElements(gl.TRIANGLES, ids.floor_count, gl.UNSIGNED_SHORT, nil) } if ids.left_buffer != 0 { gl.StencilFunc(gl.ALWAYS, 1, 1) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ids.left_buffer) do_color(R, G, B, alphaMult(A, room.far_left.wall_alpha)) gl.DrawElements(gl.TRIANGLES, ids.left_count, gl.UNSIGNED_SHORT, nil) } if ids.right_buffer != 0 { gl.StencilFunc(gl.ALWAYS, 1, 1) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ids.right_buffer) do_color(R, G, B, alphaMult(A, room.far_right.wall_alpha)) gl.DrawElements(gl.TRIANGLES, ids.right_count, gl.UNSIGNED_SHORT, nil) } } } base.EnableShader("marble") base.SetUniformI("marble", "tex2", 1) base.SetUniformF("marble", "room_x", float32(room.X)) base.SetUniformF("marble", "room_y", float32(room.Y)) for _, door := range room.Doors { door.setupGlStuff(room) if door.threshold_glids.vbuffer == 0 { continue } if door.AlwaysOpen() { continue } if door.highlight_threshold { gl.Color4ub(255, 255, 255, 255) } else { gl.Color4ub(128, 128, 128, 255) } gl.BindBuffer(gl.ARRAY_BUFFER, door.threshold_glids.vbuffer) gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x))) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u))) gl.ClientActiveTexture(gl.TEXTURE1) gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u))) gl.ClientActiveTexture(gl.TEXTURE0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, door.threshold_glids.floor_buffer) gl.DrawElements(gl.TRIANGLES, door.threshold_glids.floor_count, gl.UNSIGNED_SHORT, nil) } base.EnableShader("") if los_tex != nil { base.EnableShader("") gl.ActiveTexture(gl.TEXTURE1) gl.Disable(gl.TEXTURE_2D) gl.ActiveTexture(gl.TEXTURE0) gl.ClientActiveTexture(gl.TEXTURE1) gl.DisableClientState(gl.TEXTURE_COORD_ARRAY) gl.ClientActiveTexture(gl.TEXTURE0) } run.Assign(&floor) mul.Translation(float32(-room.X), float32(-room.Y), 0) run.Multiply(&mul) gl.LoadMatrixf(&run[0]) gl.StencilFunc(gl.EQUAL, 2, 3) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) room_rect := image.Rect(room.X, room.Y, room.X+room.Size.Dx, room.Y+room.Size.Dy) for _, fd := range floor_drawers { x, y := fd.Pos() dx, dy := fd.Dims() if room_rect.Overlaps(image.Rect(x, y, x+dx, y+dy)) { fd.RenderOnFloor() } } do_color(255, 255, 255, 255) gl.LoadIdentity() gl.Disable(gl.STENCIL_TEST) room.renderFurniture(floor, 255, drawables, los_tex) gl.ClientActiveTexture(gl.TEXTURE1) gl.Disable(gl.TEXTURE_2D) gl.ClientActiveTexture(gl.TEXTURE0) base.EnableShader("") }
func (wt *WallTexture) setupGlStuff(x, y, dx, dy int, gl_ids *wallTextureGlIds) { if gl_ids.vbuffer != 0 { gl.DeleteBuffers(1, &gl_ids.vbuffer) gl.DeleteBuffers(1, &gl_ids.left_buffer) gl.DeleteBuffers(1, &gl_ids.right_buffer) gl.DeleteBuffers(1, &gl_ids.floor_buffer) gl_ids.vbuffer = 0 gl_ids.left_buffer = 0 gl_ids.right_buffer = 0 gl_ids.floor_buffer = 0 } // All vertices for both walls and the floor will go here and get sent to // opengl all at once var vs []roomVertex // Conveniently casted values frx := float32(x) fry := float32(y) frdx := float32(dx) frdy := float32(dy) tdx := float32(wt.Texture.Data().Dx()) / 100 tdy := float32(wt.Texture.Data().Dy()) / 100 wtx := wt.X wty := wt.Y wtr := wt.Rot if wtx > frdx { wtr -= 3.1415926535 / 2 } // Floor verts := []mathgl.Vec2{ {-tdx / 2, -tdy / 2}, {-tdx / 2, tdy / 2}, {tdx / 2, tdy / 2}, {tdx / 2, -tdy / 2}, } var m, run mathgl.Mat3 run.Identity() m.Translation(wtx, wty) run.Multiply(&m) m.RotationZ(wtr) run.Multiply(&m) if wt.Flip { m.Scaling(-1, 1) run.Multiply(&m) } for i := range verts { verts[i].Transform(&run) } p := mathgl.Poly(verts) p.Clip(&mathgl.Seg2{A: mathgl.Vec2{0, 0}, B: mathgl.Vec2{0, frdy}}) p.Clip(&mathgl.Seg2{A: mathgl.Vec2{0, frdy}, B: mathgl.Vec2{frdx, frdy}}) p.Clip(&mathgl.Seg2{A: mathgl.Vec2{frdx, frdy}, B: mathgl.Vec2{frdx, 0}}) p.Clip(&mathgl.Seg2{A: mathgl.Vec2{frdx, 0}, B: mathgl.Vec2{0, 0}}) if len(p) >= 3 { // floor indices var is []uint16 for i := 1; i < len(p)-1; i++ { is = append(is, uint16(len(vs)+0)) is = append(is, uint16(len(vs)+i)) is = append(is, uint16(len(vs)+i+1)) } gl.GenBuffers(1, &gl_ids.floor_buffer) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl_ids.floor_buffer) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(int(unsafe.Sizeof(is[0]))*len(is)), gl.Pointer(&is[0]), gl.STATIC_DRAW) gl_ids.floor_count = gl.Sizei(len(is)) run.Inverse() for i := range p { v := mathgl.Vec2{p[i].X, p[i].Y} v.Transform(&run) vs = append(vs, roomVertex{ x: p[i].X, y: p[i].Y, u: v.X/tdx + 0.5, v: -(v.Y/tdy + 0.5), los_u: (fry + p[i].Y) / LosTextureSize, los_v: (frx + p[i].X) / LosTextureSize, }) } } // Left Wall verts = []mathgl.Vec2{ {-tdx / 2, -tdy / 2}, {-tdx / 2, tdy / 2}, {tdx / 2, tdy / 2}, {tdx / 2, -tdy / 2}, } run.Identity() m.Translation(wtx, wty) run.Multiply(&m) m.RotationZ(wtr) run.Multiply(&m) if wt.Flip { m.Scaling(-1, 1) run.Multiply(&m) } for i := range verts { verts[i].Transform(&run) } p = mathgl.Poly(verts) p.Clip(&mathgl.Seg2{A: mathgl.Vec2{0, 0}, B: mathgl.Vec2{0, frdy}}) p.Clip(&mathgl.Seg2{B: mathgl.Vec2{0, frdy}, A: mathgl.Vec2{frdx, frdy}}) p.Clip(&mathgl.Seg2{A: mathgl.Vec2{frdx, frdy}, B: mathgl.Vec2{frdx, 0}}) if len(p) >= 3 { // floor indices var is []uint16 for i := 1; i < len(p)-1; i++ { is = append(is, uint16(len(vs)+0)) is = append(is, uint16(len(vs)+i)) is = append(is, uint16(len(vs)+i+1)) } gl.GenBuffers(1, &gl_ids.left_buffer) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl_ids.left_buffer) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(int(unsafe.Sizeof(is[0]))*len(is)), gl.Pointer(&is[0]), gl.STATIC_DRAW) gl_ids.left_count = gl.Sizei(len(is)) run.Inverse() for i := range p { v := mathgl.Vec2{p[i].X, p[i].Y} v.Transform(&run) vs = append(vs, roomVertex{ x: p[i].X, y: frdy, z: frdy - p[i].Y, u: v.X/tdx + 0.5, v: -(v.Y/tdy + 0.5), los_u: (fry + frdy - 0.5) / LosTextureSize, los_v: (frx + p[i].X) / LosTextureSize, }) } } // Right Wall verts = []mathgl.Vec2{ {-tdx / 2, -tdy / 2}, {-tdx / 2, tdy / 2}, {tdx / 2, tdy / 2}, {tdx / 2, -tdy / 2}, } run.Identity() m.Translation(wtx, wty) run.Multiply(&m) m.RotationZ(wtr) run.Multiply(&m) if wt.Flip { m.Scaling(-1, 1) run.Multiply(&m) } for i := range verts { verts[i].Transform(&run) } p = mathgl.Poly(verts) p.Clip(&mathgl.Seg2{A: mathgl.Vec2{0, frdy}, B: mathgl.Vec2{frdx, frdy}}) p.Clip(&mathgl.Seg2{B: mathgl.Vec2{frdx, frdy}, A: mathgl.Vec2{frdx, 0}}) p.Clip(&mathgl.Seg2{A: mathgl.Vec2{frdx, 0}, B: mathgl.Vec2{0, 0}}) if len(p) >= 3 { // floor indices var is []uint16 for i := 1; i < len(p)-1; i++ { is = append(is, uint16(len(vs)+0)) is = append(is, uint16(len(vs)+i)) is = append(is, uint16(len(vs)+i+1)) } gl.GenBuffers(1, &gl_ids.right_buffer) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl_ids.right_buffer) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(int(unsafe.Sizeof(is[0]))*len(is)), gl.Pointer(&is[0]), gl.STATIC_DRAW) gl_ids.right_count = gl.Sizei(len(is)) run.Inverse() for i := range p { v := mathgl.Vec2{p[i].X, p[i].Y} v.Transform(&run) vs = append(vs, roomVertex{ x: frdx, y: p[i].Y, z: frdx - p[i].X, u: v.X/tdx + 0.5, v: -(v.Y/tdy + 0.5), los_u: (fry + p[i].Y) / LosTextureSize, los_v: (frx + frdx - 0.5) / LosTextureSize, }) } } if len(vs) > 0 { gl.GenBuffers(1, &gl_ids.vbuffer) gl.BindBuffer(gl.ARRAY_BUFFER, gl_ids.vbuffer) size := int(unsafe.Sizeof(roomVertex{})) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(size*len(vs)), gl.Pointer(&vs[0].x), gl.STATIC_DRAW) } }
func (d *Door) setupGlStuff(room *Room) { var state doorState state.facing = d.Facing state.pos = d.Pos state.room.x = room.X state.room.y = room.Y state.room.dx = room.roomDef.Size.Dx state.room.dy = room.roomDef.Size.Dy if state == d.state { return } if d.TextureData().Dy() == 0 { // Can't build this data until the texture is loaded, so we'll have to try // again later. return } d.state = state if d.threshold_glids.vbuffer != 0 { gl.DeleteBuffers(1, &d.threshold_glids.vbuffer) gl.DeleteBuffers(1, &d.threshold_glids.floor_buffer) d.threshold_glids.vbuffer = 0 d.threshold_glids.floor_buffer = 0 } if d.door_glids.vbuffer != 0 { gl.DeleteBuffers(1, &d.door_glids.vbuffer) gl.DeleteBuffers(1, &d.door_glids.floor_buffer) d.door_glids.vbuffer = 0 d.door_glids.floor_buffer = 0 } // far left, near right, do threshold // near left, far right, do threshold // far left, far right, do door var vs []roomVertex if d.Facing == FarLeft || d.Facing == NearRight { x1 := float32(d.Pos) x2 := float32(d.Pos + d.Width) var y1 float32 = -0.25 var y2 float32 = 0.25 if d.Facing == FarLeft { y1 = float32(room.roomDef.Size.Dy) y2 = float32(room.roomDef.Size.Dy) - 0.25 } // los_x1 := (x1 + float32(room.X)) / LosTextureSize vs = append(vs, roomVertex{x: x1, y: y1}) vs = append(vs, roomVertex{x: x1, y: y2}) vs = append(vs, roomVertex{x: x2, y: y2}) vs = append(vs, roomVertex{x: x2, y: y1}) for i := 0; i < 4; i++ { vs[i].los_u = (y2 + float32(room.Y)) / LosTextureSize vs[i].los_v = (vs[i].x + float32(room.X)) / LosTextureSize } } if d.Facing == FarRight || d.Facing == NearLeft { y1 := float32(d.Pos) y2 := float32(d.Pos + d.Width) var x1 float32 = -0.25 var x2 float32 = 0.25 if d.Facing == FarRight { x1 = float32(room.roomDef.Size.Dx) x2 = float32(room.roomDef.Size.Dx) - 0.25 } // los_y1 := (y1 + float32(room.Y)) / LosTextureSize vs = append(vs, roomVertex{x: x1, y: y1}) vs = append(vs, roomVertex{x: x1, y: y2}) vs = append(vs, roomVertex{x: x2, y: y2}) vs = append(vs, roomVertex{x: x2, y: y1}) for i := 0; i < 4; i++ { vs[i].los_u = (vs[i].y + float32(room.Y)) / LosTextureSize vs[i].los_v = (x2 + float32(room.X)) / LosTextureSize } } dz := -float32(d.Width*d.TextureData().Dy()) / float32(d.TextureData().Dx()) if d.Facing == FarRight { x := float32(room.roomDef.Size.Dx) y1 := float32(d.Pos + d.Width) y2 := float32(d.Pos) los_v := (float32(room.X) + x - 0.5) / LosTextureSize los_u1 := (float32(room.Y) + y1) / LosTextureSize los_u2 := (float32(room.Y) + y2) / LosTextureSize vs = append(vs, roomVertex{ x: x, y: y1, z: 0, u: 0, v: 1, los_u: los_u1, los_v: los_v, }) vs = append(vs, roomVertex{ x: x, y: y1, z: dz, u: 0, v: 0, los_u: los_u1, los_v: los_v, }) vs = append(vs, roomVertex{ x: x, y: y2, z: dz, u: 1, v: 0, los_u: los_u2, los_v: los_v, }) vs = append(vs, roomVertex{ x: x, y: y2, z: 0, u: 1, v: 1, los_u: los_u2, los_v: los_v, }) } if d.Facing == FarLeft { x1 := float32(d.Pos) x2 := float32(d.Pos + d.Width) y := float32(room.roomDef.Size.Dy) los_v1 := (float32(room.X) + x1) / LosTextureSize los_v2 := (float32(room.X) + x2) / LosTextureSize los_u := (float32(room.Y) + y - 0.5) / LosTextureSize vs = append(vs, roomVertex{ x: x1, y: y, z: 0, u: 0, v: 1, los_u: los_u, los_v: los_v1, }) vs = append(vs, roomVertex{ x: x1, y: y, z: dz, u: 0, v: 0, los_u: los_u, los_v: los_v1, }) vs = append(vs, roomVertex{ x: x2, y: y, z: dz, u: 1, v: 0, los_u: los_u, los_v: los_v2, }) vs = append(vs, roomVertex{ x: x2, y: y, z: 0, u: 1, v: 1, los_u: los_u, los_v: los_v2, }) } gl.GenBuffers(1, &d.threshold_glids.vbuffer) gl.BindBuffer(gl.ARRAY_BUFFER, d.threshold_glids.vbuffer) size := int(unsafe.Sizeof(roomVertex{})) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(size*len(vs)), gl.Pointer(&vs[0].x), gl.STATIC_DRAW) is := []uint16{0, 1, 2, 0, 2, 3} gl.GenBuffers(1, &d.threshold_glids.floor_buffer) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, d.threshold_glids.floor_buffer) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(int(unsafe.Sizeof(is[0]))*len(is)), gl.Pointer(&is[0]), gl.STATIC_DRAW) d.threshold_glids.floor_count = 6 if d.Facing == FarLeft || d.Facing == FarRight { is2 := []uint16{4, 5, 6, 4, 6, 7} gl.GenBuffers(1, &d.door_glids.floor_buffer) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, d.door_glids.floor_buffer) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(int(unsafe.Sizeof(is[0]))*len(is2)), gl.Pointer(&is2[0]), gl.STATIC_DRAW) d.door_glids.floor_count = 6 } }
func handleLoadRequest(req loadRequest) { f, _ := os.Open(req.path) im, _, err := image.Decode(f) f.Close() if err != nil { return } gray := true dx := im.Bounds().Dx() dy := im.Bounds().Dy() for i := 0; i < dx; i++ { for j := 0; j < dy; j++ { r, g, b, _ := im.At(i, j).RGBA() if r != g || g != b { gray = false break } } if !gray { break } } var canvas draw.Image var pix []byte if gray { ga := NewGrayAlpha(im.Bounds()) pix = ga.Pix canvas = ga } else { pix = memory.GetBlock(4 * req.data.dx * req.data.dy) canvas = &image.RGBA{pix, 4 * req.data.dx, im.Bounds()} } draw.Draw(canvas, im.Bounds(), im, image.Point{}, draw.Src) load_mutex.Lock() load_count += len(pix) manual_unlock := false // This prevents us from trying to send too much to opengl in a single // frame. If we go over the threshold then we hold the lock until we're // done sending data to opengl, then other requests will be free to // queue up and they will run on the next frame. if load_count < load_threshold { load_mutex.Unlock() } else { manual_unlock = true } render.Queue(func() { { gl.Enable(gl.TEXTURE_2D) gl.GenTextures(1, (*gl.Uint)(&req.data.texture)) gl.BindTexture(gl.TEXTURE_2D, req.data.texture) gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) } if gray { gl.TexImage2D( gl.TEXTURE_2D, 0, gl.LUMINANCE_ALPHA, gl.Sizei(req.data.dx), gl.Sizei(req.data.dy), 0, gl.LUMINANCE_ALPHA, gl.BYTE, gl.Pointer(&pix[0])) } else { gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(req.data.dx), gl.Sizei(req.data.dy), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&pix[0])) // gl.TexImage2D(target, level, internalformat, width, height, border, format, type_, pixels) // glu.Build2DMipmaps(gl.TEXTURE_2D, gl.RGBA, req.data.dx, req.data.dy, gl.RGBA, pix) } memory.FreeBlock(pix) if manual_unlock { load_count = 0 load_mutex.Unlock() } }) }
func (room *Room) setupGlStuff() { if room.X == room.gl.x && room.Y == room.gl.y && room.Size.Dx == room.gl.dx && room.Size.Dy == room.gl.dy && room.Wall.Data().Dx() == room.gl.wall_tex_dx && room.Wall.Data().Dy() == room.gl.wall_tex_dy { return } room.gl.x = room.X room.gl.y = room.Y room.gl.dx = room.Size.Dx room.gl.dy = room.Size.Dy room.gl.wall_tex_dx = room.Wall.Data().Dx() room.gl.wall_tex_dy = room.Wall.Data().Dy() if room.vbuffer != 0 { gl.DeleteBuffers(1, &room.vbuffer) gl.DeleteBuffers(1, &room.left_buffer) gl.DeleteBuffers(1, &room.right_buffer) gl.DeleteBuffers(1, &room.floor_buffer) } dx := float32(room.Size.Dx) dy := float32(room.Size.Dy) var dz float32 if room.Wall.Data().Dx() > 0 { dz = -float32(room.Wall.Data().Dy()*(room.Size.Dx+room.Size.Dy)) / float32(room.Wall.Data().Dx()) } // Conveniently casted values frx := float32(room.X) fry := float32(room.Y) frdx := float32(room.Size.Dx) frdy := float32(room.Size.Dy) // c is the u-texcoord of the corner of the room c := frdx / (frdx + frdy) // lt_llx := frx / LosTextureSize // lt_lly := fry / LosTextureSize // lt_urx := (frx + frdx) / LosTextureSize // lt_ury := (fry + frdy) / LosTextureSize lt_llx_ep := (frx + 0.5) / LosTextureSize lt_lly_ep := (fry + 0.5) / LosTextureSize lt_urx_ep := (frx + frdx - 0.5) / LosTextureSize lt_ury_ep := (fry + frdy - 0.5) / LosTextureSize vs := []roomVertex{ // Walls {0, dy, 0, 0, 1, lt_ury_ep, lt_llx_ep}, {dx, dy, 0, c, 1, lt_ury_ep, lt_urx_ep}, {dx, 0, 0, 1, 1, lt_lly_ep, lt_urx_ep}, {0, dy, dz, 0, 0, lt_ury_ep, lt_llx_ep}, {dx, dy, dz, c, 0, lt_ury_ep, lt_urx_ep}, {dx, 0, dz, 1, 0, lt_lly_ep, lt_urx_ep}, // Floor // This is the bulk of the floor, containing all but the outer edges of // the room. los_tex can map directly onto this so we don't need to do // anything weird here. {0.5, 0.5, 0, 0.5 / dx, 1 - 0.5/dy, lt_lly_ep, lt_llx_ep}, {0.5, dy - 0.5, 0, 0.5 / dx, 0.5 / dy, lt_ury_ep, lt_llx_ep}, {dx - 0.5, dy - 0.5, 0, 1 - 0.5/dx, 0.5 / dy, lt_ury_ep, lt_urx_ep}, {dx - 0.5, 0.5, 0, 1 - 0.5/dx, 1 - 0.5/dy, lt_lly_ep, lt_urx_ep}, {0, 0.5, 0, 0, 1 - 0.5/dy, lt_lly_ep, lt_llx_ep}, {0, dy - 0.5, 0, 0, 0.5 / dy, lt_ury_ep, lt_llx_ep}, {0.5, dy - 0.5, 0, 0.5 / dx, 0.5 / dy, lt_ury_ep, lt_llx_ep}, {0.5, 0.5, 0, 0.5 / dx, 1 - 0.5/dy, lt_lly_ep, lt_llx_ep}, {0.5, 0, 0, 0.5 / dx, 1, lt_lly_ep, lt_llx_ep}, {0.5, 0.5, 0, 0.5 / dx, 1 - 0.5/dy, lt_lly_ep, lt_llx_ep}, {dx - 0.5, 0.5, 0, 1 - 0.5/dx, 1 - 0.5/dy, lt_lly_ep, lt_urx_ep}, {dx - 0.5, 0, 0, 1 - 0.5/dx, 1, lt_lly_ep, lt_urx_ep}, {dx - 0.5, 0.5, 0, 1 - 0.5/dx, 1 - 0.5/dy, lt_lly_ep, lt_urx_ep}, {dx - 0.5, dy - 0.5, 0, 1 - 0.5/dx, 0.5 / dy, lt_ury_ep, lt_urx_ep}, {dx, dy - 0.5, 0, 1, 0.5 / dy, lt_ury_ep, lt_urx_ep}, {dx, 0.5, 0, 1, 1 - 0.5/dy, lt_lly_ep, lt_urx_ep}, {0.5, dy - 0.5, 0, 0.5 / dx, 0.5 / dy, lt_ury_ep, lt_llx_ep}, {0.5, dy, 0, 0.5 / dx, 0, lt_ury_ep, lt_llx_ep}, {dx - 0.5, dy, 0, 1 - 0.5/dx, 0, lt_ury_ep, lt_urx_ep}, {dx - 0.5, dy - 0.5, 0, 1 - 0.5/dx, 0.5 / dy, lt_ury_ep, lt_urx_ep}, {0, 0, 0, 0, 1, lt_lly_ep, lt_llx_ep}, {0, 0.5, 0, 0, 1 - 0.5/dy, lt_lly_ep, lt_llx_ep}, {0.5, 0.5, 0, 0.5 / dx, 1 - 0.5/dy, lt_lly_ep, lt_llx_ep}, {0.5, 0, 0, 0.5 / dx, 1, lt_lly_ep, lt_llx_ep}, {0, dy - 0.5, 0, 0, 0.5 / dy, lt_ury_ep, lt_llx_ep}, {0, dy, 0, 0, 0, lt_ury_ep, lt_llx_ep}, {0.5, dy, 0, 0.5 / dx, 0, lt_ury_ep, lt_llx_ep}, {0.5, dy - 0.5, 0, 0.5 / dx, 0.5 / dy, lt_ury_ep, lt_llx_ep}, {dx - 0.5, dy - 0.5, 0, 1 - 0.5/dx, 0.5 / dy, lt_ury_ep, lt_urx_ep}, {dx - 0.5, dy, 0, 1 - 0.5/dx, 0, lt_ury_ep, lt_urx_ep}, {dx, dy, 0, 1, 0, lt_ury_ep, lt_urx_ep}, {dx, dy - 0.5, 0, 1, 0.5 / dy, lt_ury_ep, lt_urx_ep}, {dx - 0.5, 0, 0, 1 - 0.5/dx, 1, lt_lly_ep, lt_urx_ep}, {dx - 0.5, 0.5, 0, 1 - 0.5/dx, 1 - 0.5/dy, lt_lly_ep, lt_urx_ep}, {dx, 0.5, 0, 1, 1 - 0.5/dy, lt_lly_ep, lt_urx_ep}, {dx, 0, 0, 1, 1, lt_lly_ep, lt_urx_ep}, } gl.GenBuffers(1, &room.vbuffer) gl.BindBuffer(gl.ARRAY_BUFFER, room.vbuffer) size := int(unsafe.Sizeof(roomVertex{})) gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(size*len(vs)), gl.Pointer(&vs[0].x), gl.STATIC_DRAW) // left wall indices is := []uint16{0, 3, 4, 0, 4, 1} gl.GenBuffers(1, &room.left_buffer) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, room.left_buffer) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(int(unsafe.Sizeof(is[0]))*len(is)), gl.Pointer(&is[0]), gl.STATIC_DRAW) // right wall indices is = []uint16{1, 4, 5, 1, 5, 2} gl.GenBuffers(1, &room.right_buffer) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, room.right_buffer) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(int(unsafe.Sizeof(is[0]))*len(is)), gl.Pointer(&is[0]), gl.STATIC_DRAW) // floor indices is = []uint16{ 6, 7, 8, 6, 8, 9, // middle 10, 11, 12, 10, 12, 13, // left side 14, 15, 16, 14, 16, 17, // bottom side 18, 19, 20, 18, 20, 21, // right side 22, 23, 24, 22, 24, 25, // top side 26, 27, 28, 26, 28, 29, // bottom left corner 30, 31, 32, 30, 32, 33, // upper left corner 34, 35, 36, 34, 36, 37, // upper right corner 38, 39, 40, 38, 40, 41, // lower right corner } gl.GenBuffers(1, &room.floor_buffer) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, room.floor_buffer) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, gl.Sizeiptr(int(unsafe.Sizeof(is[0]))*len(is)), gl.Pointer(&is[0]), gl.STATIC_DRAW) room.floor_count = len(is) }