func (t *Text) Draw() { if t.IsDebug { t.BoundingBox.Draw() } gl.UseProgram(t.font.program) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, t.font.textureID) // uniforms gl.Uniform1i(t.font.fragmentTextureUniform, 0) gl.Uniform4fv(t.font.colorUniform, 1, &t.color[0]) gl.Uniform2fv(t.font.finalPositionUniform, 1, &t.finalPosition[0]) gl.UniformMatrix4fv(t.font.orthographicMatrixUniform, 1, false, &t.font.OrthographicMatrix[0]) gl.UniformMatrix4fv(t.font.scaleMatrixUniform, 1, false, &t.scaleMatrix[0]) // draw drawCount := int32(t.RuneCount * 6) if drawCount > int32(t.eboIndexCount) { drawCount = int32(t.eboIndexCount) } if drawCount < 0 { drawCount = 0 } gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.BindVertexArray(t.vao) gl.DrawElements(gl.TRIANGLES, drawCount, gl.UNSIGNED_INT, nil) gl.BindVertexArray(0) gl.Disable(gl.BLEND) }
func CreateSprite(t Texture) (s Sprite, err error) { s.texture = t s.shader, err = CreateShader(vertexShader, fragmentShader) if err != nil { return s, err } gl.GenBuffers(1, &s.ebo) gl.GenBuffers(1, &s.vbo) gl.GenVertexArrays(1, &s.vao) gl.BindVertexArray(s.vao) gl.BindBuffer(gl.ARRAY_BUFFER, s.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, s.ebo) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices)*4, gl.Ptr(indices), gl.STATIC_DRAW) err = s.shader.SetAttrib("vert", 2, gl.FLOAT, 4*4, 0) err = s.shader.SetAttrib("vertTexCoord", 2, gl.FLOAT, 4*4, 2*4) gl.BindVertexArray(0) return s, err }
func LoadText(f *Font) (t *Text) { t = new(Text) t.font = f // text hover values // "resting state" of a text object is the min scale t.ScaleMin = 1.0 t.ScaleMax = 1.1 t.SetScale(1) // size of glfloat glfloat_size := int32(4) // stride of the buffered data xy_count := int32(2) stride := xy_count + int32(2) gl.GenVertexArrays(1, &t.vao) gl.GenBuffers(1, &t.vbo) gl.GenBuffers(1, &t.ebo) // vao gl.BindVertexArray(t.vao) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, t.font.textureID) // vbo // specify the buffer for which the VertexAttribPointer calls apply gl.BindBuffer(gl.ARRAY_BUFFER, t.vbo) gl.EnableVertexAttribArray(t.font.centeredPosition) gl.VertexAttribPointer( t.font.centeredPosition, 2, gl.FLOAT, false, glfloat_size*stride, gl.PtrOffset(0), ) gl.EnableVertexAttribArray(t.font.uv) gl.VertexAttribPointer( t.font.uv, 2, gl.FLOAT, false, glfloat_size*stride, gl.PtrOffset(int(glfloat_size*xy_count)), ) // ebo gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, t.ebo) // i am guessing that order is important here gl.BindVertexArray(0) gl.BindBuffer(gl.ARRAY_BUFFER, 0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0) return t }
func (t *Text) SetString(fs string, argv ...interface{}) { var indices []rune if len(argv) == 0 { indices = []rune(fs) } else { indices = []rune(fmt.Sprintf(fs, argv...)) } if len(indices) == 0 { return } if t.MaxRuneCount > 0 && len(indices) > t.MaxRuneCount+1 { indices = indices[0:t.MaxRuneCount] } t.String = string(indices) // ebo, vbo data glfloat_size := int32(4) t.vboIndexCount = len(indices) * 4 * 2 * 2 // 4 indexes per rune (containing 2 position + 2 texture) t.eboIndexCount = len(indices) * 6 // each rune requires 6 triangle indices for a quad t.RuneCount = len(indices) t.vboData = make([]float32, t.vboIndexCount, t.vboIndexCount) t.eboData = make([]int32, t.eboIndexCount, t.eboIndexCount) // generate the basic vbo data and bounding box t.X1 = Point{0, 0} t.X2 = Point{0, 0} t.makeBufferData(indices) // find the centered position of the bounding box lowerLeft := t.getLowerLeft() // reposition the vbo data so that it is centered at (0,0) // according to the orthographic projection being used t.setDataPosition(lowerLeft) if t.IsDebug { fmt.Printf("bounding box %v %v\n", t.X1, t.X2) fmt.Printf("lower left\n%v\n", lowerLeft) fmt.Printf("text vbo data\n%v\n", t.vboData) fmt.Printf("text ebo data\n%v\n", t.eboData) } gl.BindVertexArray(t.vao) gl.BindBuffer(gl.ARRAY_BUFFER, t.vbo) gl.BufferData( gl.ARRAY_BUFFER, int(glfloat_size)*t.vboIndexCount, gl.Ptr(t.vboData), gl.DYNAMIC_DRAW) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, t.ebo) gl.BufferData( gl.ELEMENT_ARRAY_BUFFER, int(glfloat_size)*t.eboIndexCount, gl.Ptr(t.eboData), gl.DYNAMIC_DRAW) gl.BindVertexArray(0) // not necesssary, but i just want to better understand using vertex arrays gl.BindBuffer(gl.ARRAY_BUFFER, 0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0) // SetString can be called at anytime. we want to make sure that if the user is updating the text, // the previous position will be maintained t.SetPosition(t.SetPositionX, t.SetPositionY) }
func (b *BoundingBox) Draw() { gl.UseProgram(b.program) // uniforms gl.Uniform2fv(b.finalPositionUniform, 1, &b.finalPosition[0]) gl.UniformMatrix4fv(b.orthographicMatrixUniform, 1, false, &b.font.OrthographicMatrix[0]) // draw gl.BindVertexArray(b.vao) gl.DrawElements(gl.TRIANGLES, int32(b.eboIndexCount), gl.UNSIGNED_INT, nil) gl.BindVertexArray(0) }
func (s *Sprite) Draw() { s.shader.Use() s.texture.Bind() gl.BindVertexArray(s.vao) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, s.ebo) gl.BindBuffer(gl.ARRAY_BUFFER, s.vbo) //gl.DrawArrays(gl.TRIANGLES, 0, 3) gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, gl.PtrOffset(0)) gl.BindVertexArray(0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0) }
// Updating the list of Points that this LineRender should be rendering. func (lr *LineRender) UpdatePoints(points []Point) { // Determining the buffer mode. var mode uint32 if lr.static { mode = gl.STATIC_DRAW } else { mode = gl.DYNAMIC_DRAW } // Setting the number of points. lr.points = int32(len(points)) // Generating the buffer data. vboData := generateVBOData(points) eboData := generateEBOData(len(points)) // Filling the buffer data. gl.BindVertexArray(lr.vao) gl.BindBuffer(gl.ARRAY_BUFFER, lr.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(vboData)*4, gl.Ptr(vboData), mode) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, lr.ebo) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(eboData)*4, gl.Ptr(eboData), mode) }
// Rendering this LineRender. func (lr *LineRender) Render() { // Binding the appropriate information. gl.BindVertexArray(lr.vao) gl.BindBuffer(gl.ARRAY_BUFFER, lr.vbo) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, lr.ebo) gl.UseProgram(lr.shaderProgram) // Loading up vertex attributes. vertAttrib := uint32(gl.GetAttribLocation(lr.shaderProgram, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 2, gl.FLOAT, false, 2*4, gl.PtrOffset(0)) // Line thickness information. gl.Uniform1f( gl.GetUniformLocation(lr.shaderProgram, gl.Str("in_thickness\x00")), lr.weight) // Fragment shader color information. gl.Uniform4f( gl.GetUniformLocation(lr.shaderProgram, gl.Str("in_color\x00")), lr.color.Red, lr.color.Green, lr.color.Blue, lr.color.Alpha) gl.BindFragDataLocation(lr.shaderProgram, 0, gl.Str("out_color\x00")) // Performing the render. gl.DrawElements(gl.LINE_STRIP, lr.points, gl.UNSIGNED_INT, nil) }
// Creating a RenderObject with a given shaderProgram, texture, and set of // vertices. func CreateRenderObject(shaderProgram ShaderProgram, texture Texture, vertices []float32) *RenderObject { renderObject := new(RenderObject) // Creating the basic information. renderObject.shaderProgram = uint32(shaderProgram) renderObject.texture = uint32(texture) gl.GenVertexArrays(1, &renderObject.vao) gl.GenBuffers(1, &renderObject.vbo) gl.GenBuffers(1, &renderObject.ebo) // Filling the RenderObject with information. gl.BindVertexArray(renderObject.vao) gl.BindBuffer(gl.ARRAY_BUFFER, renderObject.vbo) gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderObject.ebo) vertOrder := []uint32{ 0, 1, 2, 2, 3, 0, } gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertOrder)*4, gl.Ptr(vertOrder), gl.STATIC_DRAW) // Loading up vertex attributes. vertAttrib := uint32(gl.GetAttribLocation(renderObject.shaderProgram, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 2, gl.FLOAT, false, 4*4, gl.PtrOffset(0)) // Loading up texture attributes. texAttrib := uint32(gl.GetAttribLocation(renderObject.shaderProgram, gl.Str("vertTexCoord\x00"))) gl.EnableVertexAttribArray(texAttrib) gl.VertexAttribPointer(texAttrib, 2, gl.FLOAT, false, 4*4, gl.PtrOffset(2*4)) return renderObject }
func (c *Context) Delete() { cleanupSound() gl.BindVertexArray(0) gl.DeleteVertexArrays(1, &c.VAO) if c.window != nil { c.window.Destroy() } glfw.Terminate() }
func (p *Program) createVAO() error { gl.GenVertexArrays(1, &p.vao) if e := gl.GetError(); e != 0 { return fmt.Errorf("ERROR gl.GenVertexArray %X", e) } gl.BindVertexArray(p.vao) if e := gl.GetError(); e != 0 { return fmt.Errorf("ERROR array.Bind %X", e) } return nil }
//CreateVertexArray is a "constructor" of vertex array, hence returns a opengl //mesh, specifically a cube for testing func CreateVertexArray() VertexArray { var vertexArray VertexArray cubeVertices := vertexArray.PosData() gl.GenVertexArrays(1, &vertexArray.handleVAO) gl.BindVertexArray(vertexArray.handleVAO) gl.GenBuffers(1, &vertexArray.handleVBO) gl.BindBuffer(gl.ARRAY_BUFFER, vertexArray.handleVBO) gl.BufferData(gl.ARRAY_BUFFER, len(cubeVertices)*4, gl.Ptr(cubeVertices), gl.STATIC_DRAW) return vertexArray }
func CreateVAO() (array uint32, err error) { gl.GenVertexArrays(1, &array) if e := gl.GetError(); e != 0 { err = fmt.Errorf("ERROR gl.GenVertexArray %X", e) return } gl.BindVertexArray(array) if e := gl.GetError(); e != 0 { err = fmt.Errorf("ERROR array.Bind %X", e) return } return }
func (renderObject *RenderObject) Render() { gl.BindVertexArray(renderObject.vao) gl.BindBuffer(gl.ARRAY_BUFFER, renderObject.vbo) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderObject.ebo) gl.UseProgram(renderObject.shaderProgram) // Binding the texture. gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, renderObject.texture) gl.BindFragDataLocation(renderObject.shaderProgram, 0, gl.Str("outputColor\x00")) // Drawing the object. gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, nil) }
func CreateBuffers() { var err error program, err = MakeProgram(VertexShader(), FragmentShader()) // defer program.Delete() if err != nil { fmt.Println("Error loading shaders: " + err.Error()) panic("error loading shaders") } gl.BindFragDataLocation(program, 0, gl.Str("color\x00")) MVPid = gl.GetUniformLocation(program, gl.Str("MVP\x00")) lightpositionID = gl.GetUniformLocation(program, gl.Str("light.position\x00")) lightintensitiesID = gl.GetUniformLocation(program, gl.Str("light.intensities\x00")) lightattenuationID = gl.GetUniformLocation(program, gl.Str("light.attenuation\x00")) lightambientCoeficientID = gl.GetUniformLocation(program, gl.Str("light.ambientCoeficient\x00")) cameraPositionID = gl.GetUniformLocation(program, gl.Str("cameraPosition\x00")) // View := mathgl.LookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) // viewM = View gl.DepthFunc(gl.LEQUAL) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) // var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) // var vbo uint32 gl.GenBuffers(1, &vbo) // gl.GenBuffers(1, &elementvbo) // fmt.Println(program) gl.UseProgram(program) for idx, img := range aggregateImages { bindAggregateImage(img, idx) } }
// RenderString must be called on the render thread. x and y are the initial position of the pen, // in screen coordinates, and height is the height of a full line of text, in screen coordinates. func (d *Dictionary) RenderString(str string, x, y, height float64) { if str == "" { return } // No synchronization necessary because everything is run serially on the render thread anyway. if d.strs == nil { d.strs = make(map[string]strData) } data, ok := d.strs[str] if !ok { data = d.bindString(str) d.strs[str] = data } render.EnableShader("glop.font") defer render.EnableShader("") gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, d.atlas.texture) location, _ := render.GetUniformLocation("glop.font", "tex") gl.Uniform1i(location, 0) gl.BindSampler(0, d.atlas.sampler) location, _ = render.GetUniformLocation("glop.font", "height") gl.Uniform1f(location, float32(height)) var viewport [4]int32 gl.GetIntegerv(gl.VIEWPORT, &viewport[0]) location, _ = render.GetUniformLocation("glop.font", "screen") gl.Uniform2f(location, float32(viewport[2]), float32(viewport[3])) location, _ = render.GetUniformLocation("glop.font", "pen") gl.Uniform2f(location, float32(x)+float32(viewport[0]), float32(y)+float32(viewport[1])) location, _ = render.GetUniformLocation("glop.font", "textColor") gl.Uniform3f(location, d.color[0], d.color[1], d.color[2]) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.BindVertexArray(data.varrays[0]) gl.DrawArrays(gl.TRIANGLES, 0, data.count) }
func (c *Context) CreateWindow(w, h int, name string) (err error) { c.w = w c.h = h c.name = name var monitor *glfw.Monitor if c.fullscreen == true { monitor = glfw.GetPrimaryMonitor() } if c.window, err = glfw.CreateWindow(c.w, c.h, c.name, monitor, nil); err != nil { return } if c.cursor == false { c.window.SetInputMode(glfw.CursorMode, glfw.CursorHidden) } c.window.MakeContextCurrent() gl.Init() if e := gl.GetError(); e != 0 { if e == gl.INVALID_ENUM { fmt.Printf("GL_INVALID_ENUM when calling glInit\n") } else { err = fmt.Errorf("OpenGL glInit error: %X\n", e) return } } c.OpenGLVersion = glfw.GetVersionString() c.ShaderVersion = gl.GoStr(gl.GetString(gl.SHADING_LANGUAGE_VERSION)) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.ClearColor(0.0, 0.0, 0.0, 1.0) gl.Disable(gl.CULL_FACE) glfw.SwapInterval(1) if c.VAO, err = CreateVAO(); err != nil { return } gl.BindVertexArray(c.VAO) c.Events = NewEventHandler(c.window) return }
func main() { // init glfw if err := glfw.Init(); err != nil { panic(err) } defer glfw.Terminate() glfw.WindowHint(glfw.Resizable, glfw.False) glfw.WindowHint(glfw.ContextVersionMajor, 4) glfw.WindowHint(glfw.ContextVersionMinor, 1) glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) // make an application window window, err := glfw.CreateWindow(windowWidth, windowHeight, "Hello", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() // init gl if err := gl.Init(); err != nil { panic(err) } fmt.Println("OpenGL version", gl.GoStr(gl.GetString(gl.VERSION))) // create vertex & fragment shader program, err := newProgram(vertexShader, fragmentShader) if err != nil { panic(err) } gl.UseProgram(program) gl.BindFragDataLocation(program, 0, gl.Str("fc\x00")) points := []float32{ -0.5, -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, } vertices := []uint32{ 0, 2, 1, 3, } // configure the vertex data var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) defer gl.BindVertexArray(0) var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(points)*4, gl.Ptr(points), gl.STATIC_DRAW) var ibo uint32 gl.GenBuffers(1, &ibo) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("pv\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 2, gl.FLOAT, false, 2*4, gl.PtrOffset(0)) // global settings gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.ClearColor(1.0, 1.0, 1.0, 1.0) for !window.ShouldClose() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.UseProgram(program) gl.BindVertexArray(vao) gl.DrawElements(gl.LINE_LOOP, 4, gl.UNSIGNED_INT, gl.PtrOffset(0)) window.SwapBuffers() glfw.PollEvents() } }
func main() { // init glfw if err := glfw.Init(); err != nil { panic(err) } defer glfw.Terminate() glfw.WindowHint(glfw.Resizable, glfw.False) glfw.WindowHint(glfw.ContextVersionMajor, 4) glfw.WindowHint(glfw.ContextVersionMinor, 1) glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) // make an application window window, err := glfw.CreateWindow(windowWidth, windowHeight, "Transform", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() // init gl if err := gl.Init(); err != nil { panic(err) } fmt.Println("OpenGL version", gl.GoStr(gl.GetString(gl.VERSION))) // create vertex & fragment shader program, err := newProgram(vertexShader, fragmentShader) if err != nil { panic(err) } gl.UseProgram(program) projection := mgl32.Perspective(mgl32.DegToRad(45.0), float32(windowWidth)/windowHeight, 0.1, 10.0) projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00")) gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0]) camera := mgl32.LookAtV( mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0}, ) cameraUniform := gl.GetUniformLocation(program, gl.Str("camera\x00")) gl.UniformMatrix4fv(cameraUniform, 1, false, &camera[0]) model := mgl32.Ident4() modelUniform := gl.GetUniformLocation(program, gl.Str("model\x00")) gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) gl.BindFragDataLocation(program, 0, gl.Str("vert\x00")) points := []float32{ -0.9, -0.9, -0.9, 0.9, -0.9, -0.9, 0.9, -0.9, 0.9, -0.9, -0.9, 0.9, -0.9, 0.9, -0.9, 0.9, 0.9, -0.9, 0.9, 0.9, 0.9, -0.9, 0.9, 0.9, } vertices := []uint32{ 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 5, 2, 6, 3, 7, 4, 5, 5, 6, 6, 7, 7, 4, } // configure the vertex data var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) defer gl.BindVertexArray(0) var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(points)*4, gl.Ptr(points), gl.STATIC_DRAW) var ibo uint32 gl.GenBuffers(1, &ibo) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0)) // global settings gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.ClearColor(0.0, 0.0, 0.0, 1.0) angleX := 0.0 angleY := 0.0 angleZ := 0.0 previousTime := glfw.GetTime() for !window.ShouldClose() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) time := glfw.GetTime() elapsed := time - previousTime previousTime = time angleX += math.Sin((elapsed / period) * math.Pi * 2.0) angleY += math.Sin((elapsed / period) / 6.0 * math.Pi * 2.0) angleZ += math.Sin((elapsed / period) / 3.0 * math.Pi * 2.0) model = mgl32.HomogRotate3DY(float32(angleY)).Mul4(mgl32.HomogRotate3DX(float32(angleX))).Mul4(mgl32.HomogRotate3DZ(float32(angleZ))) gl.UseProgram(program) gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) gl.BindVertexArray(vao) gl.DrawElements(gl.LINES, int32(len(vertices)), gl.UNSIGNED_INT, gl.PtrOffset(0)) window.SwapBuffers() glfw.PollEvents() } }
func createMeshes(objs []*obj) []*mesh { var vertexTable []*objVertex var normalTable []*objNormal var texCoordTable []*objTexCoord var vertices []float32 var normals []float32 var texCoords []float32 elementIndexMap := map[objFaceElement]uint16{} var nextIndex uint16 var meshes []*mesh var iboNames []uint32 for _, o := range objs { for _, v := range o.vertices { vertexTable = append(vertexTable, v) } for _, n := range o.normals { normalTable = append(normalTable, n) } for _, tc := range o.texCoords { texCoordTable = append(texCoordTable, tc) } var indices []uint16 for _, f := range o.faces { for _, e := range f { if _, exists := elementIndexMap[e]; !exists { elementIndexMap[e] = nextIndex nextIndex++ v := vertexTable[e.vertexIndex-1] vertices = append(vertices, v.x, v.y, v.z) n := normalTable[e.normalIndex-1] normals = append(normals, n.x, n.y, n.z) // Flip the y-axis to convert from OBJ to OpenGL. // OpenGL considers the origin to be lower left. // OBJ considers the origin to be upper left. tc := texCoordTable[e.texCoordIndex-1] texCoords = append(texCoords, tc.s, 1.0-tc.t) } indices = append(indices, elementIndexMap[e]) } } meshes = append(meshes, &mesh{ id: o.id, count: int32(len(indices)), }) iboNames = append(iboNames, createElementArrayBuffer(indices)) } log.Printf("vertices: %d", len(vertexTable)) log.Printf("normals: %d", len(normalTable)) log.Printf("texCoords: %d", len(texCoordTable)) vbo := createArrayBuffer(vertices) nbo := createArrayBuffer(normals) tbo := createArrayBuffer(texCoords) const ( positionLocation = iota normalLocation texCoordLocation ) for i, m := range meshes { gl.GenVertexArrays(1, &m.vao) gl.BindVertexArray(m.vao) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.EnableVertexAttribArray(positionLocation) gl.VertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, gl.PtrOffset(0)) gl.BindBuffer(gl.ARRAY_BUFFER, nbo) gl.EnableVertexAttribArray(normalLocation) gl.VertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, gl.PtrOffset(0)) gl.BindBuffer(gl.ARRAY_BUFFER, tbo) gl.EnableVertexAttribArray(texCoordLocation) gl.VertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, gl.PtrOffset(0)) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, iboNames[i]) gl.BindVertexArray(0) } return meshes }
func (m *mesh) drawElements() { gl.BindVertexArray(m.vao) gl.DrawElements(gl.TRIANGLES, m.count, gl.UNSIGNED_SHORT, gl.Ptr(nil)) gl.BindVertexArray(0) }
func (p *Program) Unbind() { gl.BindVertexArray(0) }
func (p *Program) Bind() { gl.BindVertexArray(p.vao) gl.UseProgram(p.program) }
// bindString generates all of the vertex buffers and vertex arrays for a single constant line of // text. No error checking is done. func (d *Dictionary) bindString(str string) strData { var data strData gl.GenVertexArrays(1, &data.varrays[0]) gl.BindVertexArray(data.varrays[0]) gl.GenBuffers(2, &data.vbuffers[0]) var positions, texcoords []float32 var pen pos var prev rune for _, r := range str { ri := d.Runes[r] var scale float32 = 1.0 / float32(d.GlyphMax.Dy()) var posMin, posMax pos posMin.x = pen.x + float32(ri.GlyphBounds.Min.X)*scale posMin.y = pen.y + float32(ri.GlyphBounds.Min.Y)*scale posMax.x = pen.x + float32(ri.GlyphBounds.Max.X)*scale posMax.y = pen.y + float32(ri.GlyphBounds.Max.Y)*scale var texMin, texMax pos texMin.x = float32(ri.PixBounds.Min.X) / float32(d.Dx) texMin.y = float32(ri.PixBounds.Min.Y) / float32(d.Dy) texMax.x = float32(ri.PixBounds.Max.X) / float32(d.Dx) texMax.y = float32(ri.PixBounds.Max.Y) / float32(d.Dy) pen.x += float32(ri.AdvanceWidth) * scale pen.x += float32(d.Kerning[RunePair{prev, r}]) * scale // pen.x -= float32(d.Kerning[RunePair{prev, r}]) * scale positions = append(positions, posMin.x) // lower left positions = append(positions, posMin.y) positions = append(positions, posMin.x) // upper left positions = append(positions, posMax.y) positions = append(positions, posMax.x) // upper right positions = append(positions, posMax.y) positions = append(positions, posMin.x) // lower left positions = append(positions, posMin.y) positions = append(positions, posMax.x) // upper right positions = append(positions, posMax.y) positions = append(positions, posMax.x) // lower right positions = append(positions, posMin.y) texcoords = append(texcoords, texMin.x) // lower left texcoords = append(texcoords, texMax.y) texcoords = append(texcoords, texMin.x) // upper left texcoords = append(texcoords, texMin.y) texcoords = append(texcoords, texMax.x) // upper right texcoords = append(texcoords, texMin.y) texcoords = append(texcoords, texMin.x) // lower left texcoords = append(texcoords, texMax.y) texcoords = append(texcoords, texMax.x) // upper right texcoords = append(texcoords, texMin.y) texcoords = append(texcoords, texMax.x) // lower right texcoords = append(texcoords, texMax.y) prev = r } data.count = int32(len(positions)) gl.BindBuffer(gl.ARRAY_BUFFER, data.vbuffers[0]) gl.BufferData(gl.ARRAY_BUFFER, len(positions)*int(unsafe.Sizeof(positions[0])), gl.Ptr(&positions[0]), gl.STATIC_DRAW) location, _ := render.GetAttribLocation("glop.font", "position") gl.EnableVertexAttribArray(uint32(location)) gl.VertexAttribPointer(uint32(location), 2, gl.FLOAT, false, 0, gl.PtrOffset(0)) gl.BindBuffer(gl.ARRAY_BUFFER, data.vbuffers[1]) gl.BufferData(gl.ARRAY_BUFFER, len(texcoords)*int(unsafe.Sizeof(texcoords[0])), gl.Ptr(&texcoords[0]), gl.STATIC_DRAW) location, _ = render.GetAttribLocation("glop.font", "texCoord") gl.EnableVertexAttribArray(uint32(location)) gl.VertexAttribPointer(uint32(location), 2, gl.FLOAT, false, 0, gl.PtrOffset(0)) return data }
func main() { vertices, normals := obj.Parse(os.Args[1]) // initialize GLFW if err := glfw.Init(); err != nil { panic(err) } defer glfw.Terminate() // set opengl core profile 3.3 glfw.WindowHint(glfw.ContextVersionMajor, 3) glfw.WindowHint(glfw.ContextVersionMinor, 3) glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) window, err := glfw.CreateWindow(640, 480, "GOpenGL", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() // initialise OpenGL library if err := gl.Init(); err != nil { panic(err) } // link program from shaders program, err := newProgram("vertex.glsl", "fragment.glsl") if err != nil { panic(err) } gl.UseProgram(program) // vertex attribute object holds links between attributes and vbo var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) // vertex buffer with per-vertex data var vbo [2]uint32 gl.GenBuffers(2, &vbo[0]) // position data gl.BindBuffer(gl.ARRAY_BUFFER, vbo[0]) gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) // set up position attribute with layout of vertices posAttrib := uint32(gl.GetAttribLocation(program, gl.Str("position\x00"))) gl.VertexAttribPointer(posAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0)) gl.EnableVertexAttribArray(posAttrib) // normal data gl.BindBuffer(gl.ARRAY_BUFFER, vbo[1]) gl.BufferData(gl.ARRAY_BUFFER, len(normals)*4, gl.Ptr(normals), gl.STATIC_DRAW) normAttrib := uint32(gl.GetAttribLocation(program, gl.Str("normal\x00"))) gl.VertexAttribPointer(normAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0)) gl.EnableVertexAttribArray(normAttrib) uniModel := gl.GetUniformLocation(program, gl.Str("model\x00")) uniView := gl.GetUniformLocation(program, gl.Str("view\x00")) uniProj := gl.GetUniformLocation(program, gl.Str("proj\x00")) matView := mgl32.LookAt(2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0) gl.UniformMatrix4fv(uniView, 1, false, &matView[0]) matProj := mgl32.Perspective(mgl32.DegToRad(45.0), 640.0/480.0, 1.0, 10.0) gl.UniformMatrix4fv(uniProj, 1, false, &matProj[0]) uniLightDir := gl.GetUniformLocation(program, gl.Str("lightDir\x00")) uniLightCol := gl.GetUniformLocation(program, gl.Str("lightCol\x00")) gl.Uniform3f(uniLightDir, -0.5, 0.0, -1.0) gl.Uniform3f(uniLightCol, 0.0, 0.5, 0.5) startTime := glfw.GetTime() gl.Enable(gl.DEPTH_TEST) gl.ClearColor(1.0, 1.0, 1.0, 1.0) for !window.ShouldClose() { // clear buffer gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) matRot := mgl32.HomogRotate3DZ(float32(glfw.GetTime() - startTime)) gl.UniformMatrix4fv(uniModel, 1, false, &matRot[0]) gl.DrawArrays(gl.TRIANGLES, 0, int32(len(vertices))) window.SwapBuffers() glfw.PollEvents() } }
//Bind is the implementation of the opengl object interface. Makes this object current //in the opengl state func (vertexArray VertexArray) Bind() { gl.BindVertexArray(vertexArray.handleVAO) }
func loadBoundingBox(f *Font, X1 Point, X2 Point) (b *BoundingBox, err error) { b = new(BoundingBox) b.font = f // create shader program and define attributes and uniforms b.program, err = NewProgram(boxVertexShaderSource, boxFragmentShaderSource) if err != nil { return b, err } // ebo, vbo data b.vboIndexCount = 4 * 2 // 4 indexes per bounding box (containing 2 position) b.eboIndexCount = 6 // each rune requires 6 triangle indices for a quad b.vboData = make([]float32, b.vboIndexCount, b.vboIndexCount) b.eboData = make([]int32, b.eboIndexCount, b.eboIndexCount) b.makeBufferData(X1, X2) if f.IsDebug { fmt.Printf("bounding %v %v\n", X1, X2) fmt.Printf("bounding vbo data\n%v\n", b.vboData) fmt.Printf("bounding ebo data\n%v\n", b.eboData) } // attributes b.centeredPosition = uint32(gl.GetAttribLocation(b.program, gl.Str("centered_position\x00"))) // uniforms b.finalPositionUniform = gl.GetUniformLocation(b.program, gl.Str("final_position\x00")) b.orthographicMatrixUniform = gl.GetUniformLocation(b.program, gl.Str("orthographic_matrix\x00")) // size of glfloat glfloatSize := int32(4) gl.GenVertexArrays(1, &b.vao) gl.GenBuffers(1, &b.vbo) gl.GenBuffers(1, &b.ebo) // vao gl.BindVertexArray(b.vao) // vbo // specify the buffer for which the VertexAttribPointer calls apply gl.BindBuffer(gl.ARRAY_BUFFER, b.vbo) gl.EnableVertexAttribArray(b.centeredPosition) gl.VertexAttribPointer( b.centeredPosition, 2, gl.FLOAT, false, 0, gl.PtrOffset(0), ) gl.BufferData(gl.ARRAY_BUFFER, int(glfloatSize)*b.vboIndexCount, gl.Ptr(b.vboData), gl.DYNAMIC_DRAW) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, b.ebo) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int(glfloatSize)*b.eboIndexCount, gl.Ptr(b.eboData), gl.DYNAMIC_DRAW) gl.BindVertexArray(0) // not necesssary, but i just want to better understand using vertex arrays gl.BindBuffer(gl.ARRAY_BUFFER, 0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0) return b, nil }
func CreateContext(width, height int) Context { vertexShader := ` #version 330 uniform mat4 projection; uniform mat4 camera; uniform mat4 model; in vec3 vert; void main() { gl_Position = projection * camera * model * vec4(vert, 1); } ` + "\x00" fragmentShader := ` #version 330 uniform vec4 color; out vec4 outputColor; void main() { outputColor = color; } ` + "\x00" vertices := []float32{ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, } if err := glfw.Init(); err != nil { log.Fatalln("failed to initialize glfw:", err) } // defer glfw.Terminate() glfw.WindowHint(glfw.Resizable, glfw.False) glfw.WindowHint(glfw.ContextVersionMajor, 3) glfw.WindowHint(glfw.ContextVersionMinor, 3) glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) window, err := glfw.CreateWindow(width, height, "OpenGL", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() if err := gl.Init(); err != nil { panic(err) } program, err := newProgram(vertexShader, fragmentShader) if err != nil { panic(err) } gl.UseProgram(program) projection := mgl32.Ortho2D(0, 800, 0, 600) projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00")) gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0]) camera := mgl32.LookAtV(mgl32.Vec3{0, 0, 0.5}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0}) cameraUniform := gl.GetUniformLocation(program, gl.Str("camera\x00")) gl.UniformMatrix4fv(cameraUniform, 1, false, &camera[0]) model := mgl32.Ident4() modelUniform := gl.GetUniformLocation(program, gl.Str("model\x00")) gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0)) gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) return Context{Window: window, program: program} }
func (r *Renderable) Draw(perspective mgl.Mat4, view mgl.Mat4) { gl.UseProgram(r.Shader) gl.BindVertexArray(r.Vao) model := r.GetTransformMat4() var mvp mgl.Mat4 shaderMvp := getUniformLocation(r.Shader, "MVP_MATRIX") if shaderMvp >= 0 { mvp = perspective.Mul4(view).Mul4(model) gl.UniformMatrix4fv(shaderMvp, 1, false, &mvp[0]) } shaderMv := getUniformLocation(r.Shader, "MV_MATRIX") if shaderMv >= 0 { mv := view.Mul4(model) gl.UniformMatrix4fv(shaderMv, 1, false, &mv[0]) } shaderTex0 := getUniformLocation(r.Shader, "DIFFUSE_TEX") if shaderTex0 >= 0 { gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, r.Tex0) gl.Uniform1i(shaderTex0, 0) } shaderColor := getUniformLocation(r.Shader, "MATERIAL_DIFFUSE") if shaderColor >= 0 { gl.Uniform4f(shaderColor, r.Color[0], r.Color[1], r.Color[2], r.Color[3]) } shaderTex1 := getUniformLocation(r.Shader, "MATERIAL_TEX_0") if shaderTex1 >= 0 { gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, r.Tex0) gl.Uniform1i(shaderTex1, 0) } shaderCameraWorldPos := getUniformLocation(r.Shader, "CAMERA_WORLD_POSITION") if shaderCameraWorldPos >= 0 { gl.Uniform3f(shaderCameraWorldPos, -view[12], -view[13], -view[14]) } shaderPosition := getAttribLocation(r.Shader, "VERTEX_POSITION") if shaderPosition >= 0 { gl.BindBuffer(gl.ARRAY_BUFFER, r.VertVBO) gl.EnableVertexAttribArray(uint32(shaderPosition)) gl.VertexAttribPointer(uint32(shaderPosition), 3, gl.FLOAT, false, 0, gl.PtrOffset(0)) } shaderNormal := getAttribLocation(r.Shader, "VERTEX_NORMAL") if shaderNormal >= 0 { gl.BindBuffer(gl.ARRAY_BUFFER, r.NormsVBO) gl.EnableVertexAttribArray(uint32(shaderNormal)) gl.VertexAttribPointer(uint32(shaderNormal), 3, gl.FLOAT, false, 0, gl.PtrOffset(0)) } shaderVertUv := getAttribLocation(r.Shader, "VERTEX_UV_0") if shaderVertUv >= 0 { gl.BindBuffer(gl.ARRAY_BUFFER, r.UvVBO) gl.EnableVertexAttribArray(uint32(shaderVertUv)) gl.VertexAttribPointer(uint32(shaderVertUv), 2, gl.FLOAT, false, 0, gl.PtrOffset(0)) } gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, r.ElementsVBO) gl.DrawElements(gl.TRIANGLES, int32(r.FaceCount*3), gl.UNSIGNED_INT, gl.PtrOffset(0)) gl.BindVertexArray(0) }