func (self *Application) setup() error { gl.GenVertexArrays(1, &self.Triangles) gl.BindVertexArray(self.Triangles) trianglesVertices := []float32{ -0.9, -0.9, 0.85, -0.9, -0.9, 0.85, 0.9, -0.85, 0.9, 0.9, -0.85, 0.9, } gl.GenBuffers(1, &self.ArrayBuffer) gl.BindBuffer(gl.ARRAY_BUFFER, self.ArrayBuffer) gl.BufferData(gl.ARRAY_BUFFER, len(trianglesVertices)*4, gl.Ptr(trianglesVertices), gl.STATIC_DRAW) program, err := util.LoadShaders([]util.ShaderInfo{ util.ShaderInfo{gl.VERTEX_SHADER, "triangles.vert"}, util.ShaderInfo{gl.FRAGMENT_SHADER, "triangles.frag"}, }) if err != nil { return err } gl.UseProgram(program) gl.VertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, gl.Ptr(nil)) gl.EnableVertexAttribArray(vPosition) return nil }
/* * Creates the Vertex Array Object for a triangle. */ func createTriangleVAO(vertices []float32, indices []uint32) uint32 { var VAO uint32 gl.GenVertexArrays(1, &VAO) var VBO uint32 gl.GenBuffers(1, &VBO) var EBO uint32 gl.GenBuffers(1, &EBO) // Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointers() gl.BindVertexArray(VAO) // copy vertices data into VBO (it needs to be bound first) gl.BindBuffer(gl.ARRAY_BUFFER, VBO) gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) // copy indices into element buffer gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, EBO) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices)*4, gl.Ptr(indices), gl.STATIC_DRAW) // position gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 6*4, gl.PtrOffset(0)) gl.EnableVertexAttribArray(0) // color gl.VertexAttribPointer(1, 3, gl.FLOAT, false, 6*4, gl.PtrOffset(3*4)) gl.EnableVertexAttribArray(1) // unbind the VAO (safe practice so we don't accidentally (mis)configure it later) gl.BindVertexArray(0) return VAO }
// Load loads and sets up the model func (m *Model) Load(fileName string) { m.loadFile(fileName) shader := sm.Shader{VertSrcFile: m.data.VertShaderFile, FragSrcFile: m.data.FragShaderFile, Name: fmt.Sprintf("%s:%s", m.data.VertShaderFile, m.data.FragShaderFile)} program, err := m.shaders.LoadProgram(shader, false) if err != nil { return } m.currentProgram = program gl.UseProgram(m.currentProgram) m.projection = mgl32.Perspective(mgl32.DegToRad(45.0), float32(windowWidth)/windowHeight, 0.1, 10.0) m.projectionUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("projection\x00")) gl.UniformMatrix4fv(m.projectionUniform, 1, false, &m.projection[0]) m.camera = mgl32.LookAtV(mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0}) m.cameraUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("camera\x00")) gl.UniformMatrix4fv(m.cameraUniform, 1, false, &m.camera[0]) m.modelUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("model\x00")) gl.UniformMatrix4fv(m.modelUniform, 1, false, &m.model[0]) m.textureUniform = gl.GetUniformLocation(m.currentProgram, gl.Str("tex\x00")) gl.Uniform1i(m.textureUniform, 0) gl.BindFragDataLocation(m.currentProgram, 0, gl.Str("outputColor\x00")) // Load the texture m.textures.LoadTexture(m.data.TextureFile, m.data.TextureFile) // Configure the vertex data gl.GenVertexArrays(1, &m.vao) gl.BindVertexArray(m.vao) var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(m.data.Verts)*4, gl.Ptr(m.data.Verts), gl.STATIC_DRAW) vertAttrib := uint32(gl.GetAttribLocation(m.currentProgram, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, m.data.VertSize*4, gl.PtrOffset(0)) // 4:number of bytes in a float32 texCoordAttrib := uint32(gl.GetAttribLocation(m.currentProgram, gl.Str("vertTexCoord\x00"))) gl.EnableVertexAttribArray(texCoordAttrib) gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, true, m.data.VertSize*4, gl.PtrOffset(3*4)) // 4:number of bytes in a float32 if m.data.Indexed { var indices uint32 gl.GenBuffers(1, &indices) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(m.data.Indices)*4, gl.Ptr(m.data.Indices), gl.STATIC_DRAW) } gl.BindVertexArray(0) }
// CreateGeometry - add geometry to the renderer func (glRenderer *OpenglRenderer) CreateGeometry(geometry *renderer.Geometry) { var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(geometry.Verticies)*4, gl.Ptr(geometry.Verticies), gl.DYNAMIC_DRAW) geometry.VboId = vbo var ibo uint32 gl.GenBuffers(1, &ibo) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(geometry.Indicies)*4, gl.Ptr(geometry.Indicies), gl.DYNAMIC_DRAW) geometry.IboId = ibo }
func (glRenderer *OpenglRenderer) loadTexture(img image.Image, textureUnit uint32, lod bool) uint32 { rgba := image.NewRGBA(img.Bounds()) if rgba.Stride != rgba.Rect.Size().X*4 { log.Fatal("unsupported stride") } draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) var texId uint32 gl.GenTextures(1, &texId) gl.ActiveTexture(textureUnit) gl.BindTexture(gl.TEXTURE_2D, texId) if rgba.Rect.Size().X == 0 || rgba.Rect.Size().Y == 0 { return texId } gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Size().X), int32(rgba.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix), ) 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) if lod { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.GenerateMipmap(gl.TEXTURE_2D) } else { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) } return texId }
func createVbo(points []float32) uint32 { var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(points)*4, gl.Ptr(&points[0]), gl.STATIC_DRAW) return vbo }
/* * Creates the Vertex Array Object for a triangle. */ func createTriangleVAO() uint32 { vertices := []float32{ -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0, } var VAO uint32 gl.GenVertexArrays(1, &VAO) var VBO uint32 gl.GenBuffers(1, &VBO) // Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointers() gl.BindVertexArray(VAO) // copy vertices data into VBO (it needs to be bound first) gl.BindBuffer(gl.ARRAY_BUFFER, VBO) gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) // specify the format of our vertex input // (shader) input 0 // vertex has size 3 // vertex items are of type FLOAT // do not normalize (already done) // stride of 3 * sizeof(float) (separation of vertices) // offset of where the position data starts (0 for the beginning) gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0)) gl.EnableVertexAttribArray(0) // unbind the VAO (safe practice so we don't accidentally (mis)configure it later) gl.BindVertexArray(0) return VAO }
/* * Creates the Vertex Array Object for a triangle. * indices is leftover from earlier samples and not used here. */ func createVAO(vertices []float32, indices []uint32) uint32 { var VAO uint32 gl.GenVertexArrays(1, &VAO) var VBO uint32 gl.GenBuffers(1, &VBO) var EBO uint32 gl.GenBuffers(1, &EBO) // Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointers() gl.BindVertexArray(VAO) // copy vertices data into VBO (it needs to be bound first) gl.BindBuffer(gl.ARRAY_BUFFER, VBO) gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW) // size of one whole vertex (sum of attrib sizes) var stride int32 = 3*4 + 2*4 var offset int = 0 // position gl.VertexAttribPointer(0, 3, gl.FLOAT, false, stride, gl.PtrOffset(offset)) gl.EnableVertexAttribArray(0) offset += 3 * 4 // unbind the VAO (safe practice so we don't accidentally (mis)configure it later) gl.BindVertexArray(0) return VAO }
/* Binds the VBO and buffers data to the GPU */ func (vbo *VertexBuffer) Buffer(vertices VertexData) error { // bind buffer err := vbo.Bind() if err != nil { return err } // buffer data to GPU size := vertices.Size() * vertices.Elements() ptr := gl.Ptr(vertices) gl.BufferData(vbo.Target, size, ptr, vbo.Usage) // check actual size in GPU memory var gpuSize int32 = 0 gl.GetBufferParameteriv(vbo.Target, gl.BUFFER_SIZE, &gpuSize) if int(gpuSize) != size { return fmt.Errorf("Failed buffering data to buffer #%d, expected size %d bytes, actual: %d bytes", vbo.Id, size, gpuSize) } vbo.Size = vertices.Size() vbo.Elements = vertices.Elements() // debug logging fmt.Printf("[VBO %d] Buffered %d x %d = %d bytes\n", vbo.Id, vbo.Size, vbo.Elements, size) return nil }
func (me *GlObj) AddProperty(location uint32, buf []float32, size, stride int32, offset int) { var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(buf)*FloatSize, gl.Ptr(buf), gl.STATIC_DRAW) gl.EnableVertexAttribArray(location) gl.VertexAttribPointer(location, size, gl.FLOAT, false, stride*FloatSize, gl.PtrOffset(offset*FloatSize)) }
func (me *GlObj) AddProperty(i uint32, buf []float32, size int32) { var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(buf)*4, gl.Ptr(buf), gl.STATIC_DRAW) gl.EnableVertexAttribArray(i) gl.VertexAttribPointer(i, size, gl.FLOAT, false, 0, gl.PtrOffset(0)) }
func (glRenderer *OpenglRenderer) loadCubeMap(right, left, top, bottom, back, front image.Image, textureUnit uint32, lod bool) uint32 { var texId uint32 gl.GenTextures(1, &texId) gl.ActiveTexture(textureUnit) gl.BindTexture(gl.TEXTURE_CUBE_MAP, texId) for i := 0; i < 6; i++ { img := right var texIndex uint32 = gl.TEXTURE_CUBE_MAP_POSITIVE_X switch i { case 1: img = left texIndex = gl.TEXTURE_CUBE_MAP_NEGATIVE_X case 2: img = top texIndex = gl.TEXTURE_CUBE_MAP_NEGATIVE_Y case 3: img = bottom texIndex = gl.TEXTURE_CUBE_MAP_POSITIVE_Y case 4: img = back texIndex = gl.TEXTURE_CUBE_MAP_NEGATIVE_Z case 5: img = front texIndex = gl.TEXTURE_CUBE_MAP_POSITIVE_Z } img = imaging.FlipV(img) rgba := image.NewRGBA(img.Bounds()) if rgba.Stride != rgba.Rect.Size().X*4 { log.Fatal("unsupported stride") } draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) gl.TexImage2D( texIndex, 0, gl.RGBA, int32(rgba.Rect.Size().X), int32(rgba.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix), ) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE) if lod { gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.GenerateMipmap(gl.TEXTURE_CUBE_MAP) } else { gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR) } } return texId }
/** Buffers texture data to GPU memory */ func (tx *Texture) Buffer(img *image.RGBA) { /* Buffer image data */ gl.TexImage2D( gl.TEXTURE_2D, 0, int32(tx.InternalFormat), tx.Width, tx.Height, 0, tx.Format, tx.DataType, gl.Ptr(img.Pix)) }
// NewBillboard creates a 2D billboard for rendering func (font *Font) NewBillboard(text string, maxWidth int, maxHeight int, size float64, dpi float64, color color.Color) *Billboard { b := &Billboard{} b.texWidth = maxWidth b.texHeight = maxHeight image, renderedWidth, renderedHeight := font.createTexture(text, b.texWidth, b.texHeight, size, dpi, color) b.size = size b.dpi = dpi b.text = text b.font = font b.rgba = color b.Width = renderedWidth b.Height = renderedHeight var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) w := float32(maxWidth) h := float32(maxHeight) billboardVertices := []float32{ w, h, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0.0, 1.0, w, h, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, w, 0.0, 0.0, 1.0, 0.0, } gl.BufferData(gl.ARRAY_BUFFER, len(billboardVertices)*4, gl.Ptr(billboardVertices), gl.STATIC_DRAW) vertAttrib := uint32(0) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0)) texCoordAttrib := uint32(1) gl.EnableVertexAttribArray(texCoordAttrib) gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4)) b.vao = vao b.image = image return b }
//Set up the frame buffer for rendering each post effect filter pass func (glRenderer *OpenglRenderer) initPostEffects() { //post effects quad verts := []float32{ -1, -1, 0, 0, 1, -1, 1, 0, -1, 1, 0, 1, 1, 1, 1, 1, } var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(verts)*4, gl.Ptr(verts), gl.STATIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) glRenderer.postEffectVbo = vbo }
func NewTexture(file string, linear bool) (err error, texture *Texture, img image.Image) { var imgFile *os.File if imgFile, err = os.Open(file); err != nil { return err, nil, img } defer imgFile.Close() if img, _, err = image.Decode(imgFile); err != nil { return err, nil, img } var rgba *image.RGBA rgba = image.NewRGBA(img.Bounds()) if rgba.Stride != rgba.Rect.Size().X*4 { return fmt.Errorf("unsupported stride"), nil, img } draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) var t uint32 gl.GenTextures(1, &t) texture = &Texture{t, rgba.Rect.Size()} texture.BindTexture(0) if linear { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) } else { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) } 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.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Size().X), int32(rgba.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) return nil, texture, img }
func (me *Core) AddTexture(file string) int { imgFile, err := os.Open(file) if err != nil { fmt.Println("Could not open file:", file) panic(err) } img, _, err := image.Decode(imgFile) if err != nil { fmt.Println("Could not decode file:", file) panic(err) } rgba := image.NewRGBA(img.Bounds()) if rgba.Stride != rgba.Rect.Size().X*FloatSize { fmt.Println("Stride unsupported, file:", file) panic(err) } draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) var texture uint32 gl.GenTextures(1, &texture) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, texture) 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.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Size().X), int32(rgba.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) n := me.nbTexture me.Textures[n] = texture me.nbTexture++ return n }
func NewFont(file string, rows int) (err error, font *Font) { var imgFile *os.File if imgFile, err = os.Open(file); err != nil { return err, nil } defer imgFile.Close() var img image.Image if img, _, err = image.Decode(imgFile); err != nil { return err, nil } gray := image.NewGray(img.Bounds()) if gray.Stride != gray.Rect.Size().X { return fmt.Errorf("unsupported stride"), nil } draw.Draw(gray, gray.Bounds(), img, image.Point{0, 0}, draw.Src) var t uint32 gl.GenTextures(1, &t) var texture *Texture = &Texture{t, gray.Rect.Size()} texture.BindTexture(0) 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.TexImage2D( gl.TEXTURE_2D, 0, gl.R8, int32(gray.Rect.Size().X), int32(gray.Rect.Size().Y), 0, gl.RED, gl.UNSIGNED_BYTE, gl.Ptr(gray.Pix)) font = &Font{texture, nil, rows, gray.Rect.Size().X / rows} return nil, font }
func (font *Font) createTexture(text string, width int, height int, size float64, dpi float64, rgba color.Color) (uint32, int, int) { context := freetype.NewContext() context.SetFont(font.ttf) img := image.NewRGBA(image.Rect(0, 0, width, height)) r, g, b, _ := rgba.RGBA() draw.Draw(img, img.Bounds(), image.NewUniform(color.RGBA{uint8(r), uint8(g), uint8(b), 0}), image.ZP, draw.Src) context.SetDst(img) context.SetClip(img.Bounds()) context.SetSrc(image.NewUniform(rgba)) context.SetFontSize(size) context.SetDPI(dpi) pixelBounds, _ := context.DrawString(text, freetype.Pt(0, height/2)) var tex uint32 gl.GenTextures(1, &tex) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, tex) 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.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, tex) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(img.Rect.Size().X), int32(img.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(img.Pix)) return tex, int26_6Ceiling(pixelBounds.X + 0x3f), int26_6Ceiling(pixelBounds.Y + 0x3f) }
func (t *Texture) create(file string) error { imgFile, err := os.Open(file) if err != nil { return fmt.Errorf("texture %q not found on disk: %v", file, err) } img, _, err := image.Decode(imgFile) if err != nil { return err } rgba := image.NewRGBA(img.Bounds()) if rgba.Stride != rgba.Rect.Size().X*4 { return fmt.Errorf("unsupported stride") } draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) var tex uint32 gl.GenTextures(1, &tex) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, tex) 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.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Size().X), int32(rgba.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) t.id = tex t.Width = rgba.Rect.Size().X t.Height = rgba.Rect.Size().Y return nil }
func NewTexture(img image.Image, wrapR, wrapS int32) (*Texture, error) { rgba := image.NewRGBA(img.Bounds()) draw.Draw(rgba, rgba.Bounds(), img, image.Pt(0, 0), draw.Src) if rgba.Stride != rgba.Rect.Size().X*4 { // TODO-cs: why? return nil, errUnsupportedStride } var handle uint32 gl.GenTextures(1, &handle) target := uint32(gl.TEXTURE_2D) internalFmt := int32(gl.SRGB_ALPHA) format := uint32(gl.RGBA) width := int32(rgba.Rect.Size().X) height := int32(rgba.Rect.Size().Y) pixType := uint32(gl.UNSIGNED_BYTE) dataPtr := gl.Ptr(rgba.Pix) texture := Texture{ handle: handle, target: target, } texture.Bind(gl.TEXTURE0) defer texture.UnBind() // set the texture wrapping/filtering options (applies to current bound texture obj) // TODO-cs gl.TexParameteri(texture.target, gl.TEXTURE_WRAP_R, wrapR) gl.TexParameteri(texture.target, gl.TEXTURE_WRAP_S, wrapS) gl.TexParameteri(texture.target, gl.TEXTURE_MIN_FILTER, gl.LINEAR) // minification filter gl.TexParameteri(texture.target, gl.TEXTURE_MAG_FILTER, gl.LINEAR) // magnification filter gl.TexImage2D(target, 0, internalFmt, width, height, 0, format, pixType, dataPtr) gl.GenerateMipmap(texture.handle) return &texture, nil }
func NewTexture(assetName string) (uint32, error) { data, err := Asset(assetName) if err != nil { return 0, err } img, _, err := image.Decode(bytes.NewReader(data)) if err != nil { return 0, err } rgba := image.NewRGBA(img.Bounds()) if rgba.Stride != rgba.Rect.Size().X*4 { return 0, fmt.Errorf("unsupported stride") } draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src) var texture uint32 gl.GenTextures(1, &texture) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, texture) 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.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(rgba.Rect.Size().X), int32(rgba.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) return texture, nil }
func (renderer *Renderer) Loop() { defer glog.Flush() if err := glfw.Init(); err != nil { glog.Fatalln("GLFW failed to initialize:", err) glog.Info("GLFW failed to init") } glfw.WindowHint(glfw.ContextVersionMajor, 3) glfw.WindowHint(glfw.ContextVersionMinor, 2) glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) glfw.WindowHint(glfw.Resizable, glfw.False) window, windowError := glfw.CreateWindow(800, 600, "OpenGL", nil, nil) if windowError != nil { glog.Info("oops") panic(windowError) } glog.Info("Buffer") defer func() { window.Destroy() glfw.Terminate() glog.Info("ending") renderer.ended = true //system_end <- true }() window.MakeContextCurrent() if err := gl.Init(); err != nil { panic(err) } renderer.keyCallback = func(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) { glog.Infof("key: %v, scancode: %v, action: %v, mods: %v", key, scancode, action, mods) } window.SetKeyCallback(renderer.keyCallback) //<-system_start renderer.started = true //system_started <- true gl.ClearDepth(1.0) var vboID uint32 gl.GenBuffers(1, &vboID) var vertexData = []float32{ 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, } gl.BindBuffer(gl.ARRAY_BUFFER, vboID) gl.BufferData(gl.ARRAY_BUFFER, len(vertexData)*4, gl.Ptr(vertexData), gl.STATIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) //get shaders vertexShader, fragmentShader := getShaders() program, err := newProgram(vertexShader, fragmentShader) program.UseProgram() if err != nil { panic(err) } //bind attributes // L: for !window.ShouldClose() { //renderer.drawGame(program) gl.EnableVertexAttribArray(0) gl.BindBuffer(gl.ARRAY_BUFFER, vboID) gl.VertexAttribPointer( 0, 3, gl.FLOAT, false, 0, gl.PtrOffset(0)) gl.DrawArrays(gl.TRIANGLES, 0, 3) gl.DisableVertexAttribArray(0) window.SwapBuffers() glfw.PollEvents() } if vboID != 0 { gl.DeleteBuffers(1, &vboID) } }
func (glRenderer *OpenglRenderer) DrawGeometry(geometry *renderer.Geometry, transform mgl32.Mat4) { glRenderer.enableShader() glRenderer.enableMaterial() glRenderer.enableCubeMap() if glRenderer.activeShader == nil { panic("ERROR: No shader is configured.") } shader := glRenderer.activeShader program := shader.Program params := glRenderer.rendererParams glRenderer.enableDepthTest(params.DepthTest) glRenderer.enableDepthMask(params.DepthMask) glRenderer.enableCullFace(params.CullBackface) glRenderer.enableUnlit(params.Unlit) glRenderer.setTransparency(params.Transparency) // set buffers gl.BindBuffer(gl.ARRAY_BUFFER, geometry.VboId) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, geometry.IboId) // update buffers if geometry.VboDirty && len(geometry.Verticies) > 0 && len(geometry.Indicies) > 0 { gl.BufferData(gl.ARRAY_BUFFER, len(geometry.Verticies)*4, gl.Ptr(geometry.Verticies), gl.DYNAMIC_DRAW) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(geometry.Indicies)*4, gl.Ptr(geometry.Indicies), gl.DYNAMIC_DRAW) geometry.VboDirty = false } // set uniforms modelNormal := transform.Inv().Transpose() shader.Uniforms["model"] = transform shader.Uniforms["modelNormal"] = modelNormal // set camera uniforms cam := glRenderer.camera win := glRenderer.WindowDimensions() shader.Uniforms["cameraTranslation"] = cam.Translation if cam.Ortho { shader.Uniforms["projection"] = mgl32.Ortho2D(0, win.X(), win.Y(), 0) shader.Uniforms["camera"] = mgl32.Ident4() } else { shader.Uniforms["projection"] = mgl32.Perspective(mgl32.DegToRad(cam.Angle), win.X()/win.Y(), cam.Near, cam.Far) shader.Uniforms["camera"] = mgl32.LookAtV(cam.Translation, cam.Lookat, cam.Up) } shader.Uniforms["unlit"] = glRenderer.unlit shader.Uniforms["useTextures"] = glRenderer.useTextures shader.Uniforms["ambientLightValue"] = glRenderer.ambientLightValue shader.Uniforms["nbPointLights"] = glRenderer.nbPointLights shader.Uniforms["pointLightValues"] = glRenderer.pointLightValues shader.Uniforms["pointLightPositions"] = glRenderer.pointLightPositions shader.Uniforms["nbDirectionalLights"] = glRenderer.nbDirectionalLights shader.Uniforms["directionalLightValues"] = glRenderer.directionalLightValues shader.Uniforms["directionalLightVectors"] = glRenderer.directionalLightVectors // set custom uniforms setupUniforms(shader) // set verticies attribute vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, renderer.VertexStride*4, gl.PtrOffset(0)) // set normals attribute normAttrib := uint32(gl.GetAttribLocation(program, gl.Str("normal\x00"))) gl.EnableVertexAttribArray(normAttrib) gl.VertexAttribPointer(normAttrib, 3, gl.FLOAT, false, renderer.VertexStride*4, gl.PtrOffset(3*4)) // set texture coord attribute texCoordAttrib := uint32(gl.GetAttribLocation(program, gl.Str("texCoord\x00"))) gl.EnableVertexAttribArray(texCoordAttrib) gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, renderer.VertexStride*4, gl.PtrOffset(6*4)) // vertex color attribute colorAttrib := uint32(gl.GetAttribLocation(program, gl.Str("color\x00"))) gl.EnableVertexAttribArray(colorAttrib) gl.VertexAttribPointer(colorAttrib, 4, gl.FLOAT, false, renderer.VertexStride*4, gl.PtrOffset(8*4)) gl.DrawElements(gl.TRIANGLES, (int32)(len(geometry.Indicies)), gl.UNSIGNED_INT, gl.PtrOffset(0)) }
func (sprite *Sprite) create(file string, width int, height int, frames int, framesPerLine int) error { image, err := texture.New(file) if err != nil { return err } var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) w := float32(width) h := float32(height) frameWidth := float32(width) / float32(image.Width) frameHeight := float32(height) / float32(image.Height) var spriteVertices []float32 if frames == 0 { spriteVertices = []float32{ w, h, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0.0, 1.0, w, h, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, w, 0.0, 0.0, 1.0, 0.0, } } else { for i := 0; i < frames; i++ { frameX := float32(i%framesPerLine) * frameWidth frameY := float32(i/framesPerLine) * frameHeight frameW := frameWidth + frameX frameH := frameHeight + frameY spriteVertices = append(spriteVertices, []float32{ w, h, 0.0, frameW, frameH, 0.0, 0.0, 0.0, frameX, frameY, 0.0, h, 0.0, frameX, frameH, w, h, 0.0, frameW, frameH, 0.0, 0.0, 0.0, frameX, frameY, w, 0.0, 0.0, frameW, frameY, }...) } } gl.BufferData(gl.ARRAY_BUFFER, len(spriteVertices)*4, gl.Ptr(spriteVertices), gl.STATIC_DRAW) vertAttrib := uint32(0) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0)) texCoordAttrib := uint32(1) gl.EnableVertexAttribArray(texCoordAttrib) gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4)) sprite.vao = vao sprite.image = image return nil }
func main() { 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, 4) glfw.WindowHint(glfw.ContextVersionMinor, 1) glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True) window, err := glfw.CreateWindow(windowWidth, windowHeight, "Cube", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() // Initialize Glow if err := gl.Init(); err != nil { panic(err) } version := gl.GoStr(gl.GetString(gl.VERSION)) fmt.Println("OpenGL version", version) // Configure the vertex and fragment shaders 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]) textureUniform := gl.GetUniformLocation(program, gl.Str("tex\x00")) gl.Uniform1i(textureUniform, 0) gl.BindFragDataLocation(program, 0, gl.Str("outputColor\x00")) // Load the texture texture, err := newTexture("square.png") if err != nil { panic(err) } // Configure the vertex data 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(cubeVertices)*4, gl.Ptr(cubeVertices), gl.STATIC_DRAW) vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00"))) gl.EnableVertexAttribArray(vertAttrib) gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0)) texCoordAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vertTexCoord\x00"))) gl.EnableVertexAttribArray(texCoordAttrib) gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4)) // Configure global settings gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.ClearColor(1.0, 1.0, 1.0, 1.0) angle := 0.0 previousTime := glfw.GetTime() for !window.ShouldClose() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) // Update time := glfw.GetTime() elapsed := time - previousTime previousTime = time angle += elapsed model = mgl32.HomogRotate3D(float32(angle), mgl32.Vec3{0, 1, 0}) // Render gl.UseProgram(program) gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) gl.BindVertexArray(vao) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, texture) gl.DrawArrays(gl.TRIANGLES, 0, 6*2*3) // Maintenance window.SwapBuffers() glfw.PollEvents() } }
func (font *Font) updateTexture(texture uint32, text string, width int, height int, size float64, dpi float64, rgba color.Color) (int, int) { context := freetype.NewContext() context.SetFont(font.ttf) img := image.NewRGBA(image.Rect(0, 0, width, height)) r, g, b, _ := rgba.RGBA() draw.Draw(img, img.Bounds(), image.NewUniform(color.RGBA{uint8(r), uint8(g), uint8(b), 0}), image.ZP, draw.Src) context.SetDst(img) context.SetClip(img.Bounds()) context.SetSrc(image.NewUniform(rgba)) context.SetFontSize(size) context.SetDPI(dpi) pixelBounds, _ := context.DrawString(text, freetype.Pt(0, height/2)) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, texture) gl.TexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, int32(img.Rect.Size().X), int32(img.Rect.Size().Y), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(img.Pix)) return int26_6Ceiling(pixelBounds.X + 0x3f), int26_6Ceiling(pixelBounds.Y + 0x3f) }