func (c SpritesheetFrameConfig) ToSpritesheetFrame() *SpritesheetFrame { var ( texX = c.textureX / c.textureOriginalW texY = c.textureY / c.textureOriginalH texW = c.textureW / c.textureOriginalW texH = c.textureH / c.textureOriginalH ) var ( texMove = mgl32.Translate3D(texX, -texH-texY, 0.0) texScale = mgl32.Scale3D(texW, texH, 1.0) texRotate = mgl32.HomogRotate3DZ(mgl32.DegToRad(0)) texAdj = texMove.Mul4(texScale).Mul4(texRotate).Transpose() ) var ( ptScale = mgl32.Scale3D(c.sourceW/c.pxPerUnit, c.sourceH/c.pxPerUnit, 1.0) ptAdj = ptScale.Transpose() ) return &SpritesheetFrame{ Frame: FrameConfig{ PointAdjustment: ptAdj, TextureAdjustment: texAdj, }, Width: c.sourceW / c.pxPerUnit, Height: c.sourceH / c.pxPerUnit, } }
/* Update transform matrix and right/up/forward vectors */ func (t *Transform) Update(dt float32) { // todo: avoid recalculating unless something has changed /* Update transform */ rad := t.Rotation.Mul(math.Pi / 180.0) // translate rotaiton to radians rotation := mgl.AnglesToQuat(rad[0], rad[1], rad[2], mgl.XYZ).Mat4() scaling := mgl.Scale3D(t.Scale[0], t.Scale[1], t.Scale[2]) translation := mgl.Translate3D(t.Position[0], t.Position[1], t.Position[2]) /* New transform matrix: S * R * T */ //m := scaling.Mul4(rotation.Mul4(translation)) m := translation.Mul4(rotation.Mul4(scaling)) /* Grab axis vectors from transformation matrix */ t.Right[0] = m[4*0+0] // first column t.Right[1] = m[4*1+0] t.Right[2] = m[4*2+0] t.Up[0] = m[4*0+1] // second column t.Up[1] = m[4*1+1] t.Up[2] = m[4*2+1] t.Forward[0] = -m[4*0+2] // third column t.Forward[1] = -m[4*1+2] t.Forward[2] = -m[4*2+2] /* Update transformation matrix */ t.Matrix = m }
func TestStackMultiPush(t *testing.T) { stack := NewTransformStack() scale := mgl32.Scale3D(2, 2, 2) rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90)) trans := mgl32.Translate3D(4, 5, 6) stack.Push(trans) stack.Push(rot) if !stack.Peek().ApproxEqualThreshold(trans.Mul4(rot), 1e-4) { t.Errorf("Stack does not multiply first two pushes correctly") } stack.Push(scale) if !stack.Peek().ApproxEqualThreshold(trans.Mul4(rot).Mul4(scale), 1e-4) { t.Errorf("Stack does not multiple third push correctly") } stack.Unwind(2) stack.Push(scale) if !stack.Peek().ApproxEqualThreshold(trans.Mul4(scale), 1e-4) { t.Errorf("Unwinding and multiplying does not work correctly") } }
func ExampleRebase() { parent1 := NewTransformStack() scale := mgl32.Scale3D(2, 2, 2) rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90)) trans := mgl32.Translate3D(5, 5, 5) parent1.Push(trans) parent1.Push(rot) parent1.Push(scale) parent2 := parent1.Copy() trans2 := mgl32.Translate3D(1, 1, 1) rot2 := mgl32.HomogRotate3DX(mgl32.DegToRad(45)) parent1.Push(trans2) parent1.Push(rot2) // Replay the pushes the changes from parent1 after the copy onto parent2, as if // they had been done on parent2 instead parent2, err := Rebase(parent1, 4, parent2) if err != nil { panic(err) } // Now parent2 and parent 1 should be the same! fmt.Println(parent2.Peek().ApproxEqualThreshold(parent1.Peek(), 1e-4)) // Output: true }
func onPaint(glctx gl.Context, sz size.Event) { glctx.Viewport(0, 0, sz.WidthPx, sz.HeightPx) glctx.ClearColor(0.5, 0.5, 0.5, 1) glctx.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) glctx.UseProgram(program) projectionMtx = mgl32.Perspective(45, float32(width)/float32(height), 0.1, 100) arcBallMtx := arcball.getMtx() glctx.UniformMatrix4fv(projection, projectionMtx[:]) glctx.UniformMatrix4fv(view, arcBallMtx[:]) glctx.BindBuffer(gl.ARRAY_BUFFER, triBuf) glctx.EnableVertexAttribArray(position) glctx.EnableVertexAttribArray(color) glctx.EnableVertexAttribArray(normals) vertSize := 4 * (coordsPerVertex + colorPerVertex + normalsPerVertex) glctx.VertexAttribPointer(position, coordsPerVertex, gl.FLOAT, false, vertSize, 0) glctx.VertexAttribPointer(color, colorPerVertex, gl.FLOAT, false, vertSize, 4*coordsPerVertex) glctx.VertexAttribPointer(normals, normalsPerVertex, gl.FLOAT, false, vertSize, 4*(coordsPerVertex+colorPerVertex)) glctx.DepthMask(true) glctx.Uniform3fv(lightPos, light.Pos[:]) glctx.Uniform3fv(lightIntensity, light.Intensities[:]) for _, k := range piano.Keys { glctx.Uniform4fv(tint, k.Color[:]) mtx := k.GetMtx() normMat := mtx.Mat3().Inv().Transpose() glctx.UniformMatrix3fv(normalMatrix, normMat[:]) glctx.UniformMatrix4fv(model, mtx[:]) glctx.DrawArrays(gl.TRIANGLES, 0, len(triangleData)/vertSize) } modelMtx := mgl32.Ident4() modelMtx = modelMtx.Mul4(mgl32.Translate3D(worldPos.X(), worldPos.Y(), worldPos.Z())) modelMtx = modelMtx.Mul4(mgl32.Scale3D(0.5, 0.5, 0.5)) /* glctx.Uniform4fv(tint, red[:]) // Disable depthmask so we dont get the pixel depth of the cursor cube glctx.DepthMask(false) glctx.UniformMatrix4fv(model, modelMtx[:]) glctx.DepthMask(true) */ glctx.DisableVertexAttribArray(position) glctx.DisableVertexAttribArray(color) glctx.DisableVertexAttribArray(normals) fps.Draw(sz) }
// GetTransformMat4 creates a transform matrix: scale * transform func (r *Renderable) GetTransformMat4() mgl.Mat4 { scaleMat := mgl.Scale3D(r.Scale[0], r.Scale[1], r.Scale[2]) transMat := mgl.Translate3D(r.Location[0], r.Location[1], r.Location[2]) localRotMat := r.LocalRotation.Mat4() rotMat := r.Rotation.Mat4() modelTransform := rotMat.Mul4(transMat).Mul4(localRotMat).Mul4(scaleMat) return modelTransform }
func (t *Text) SetScale(s float32) (changed bool) { if s > t.ScaleMax || s < t.ScaleMin { return } changed = true t.Scale = s t.scaleMatrix = mgl32.Scale3D(s, s, s) return }
func (this *TextRenderer) TextTransform(vertex mathgl.Vec4) mathgl.Vec4 { // apply font transforms scale := float32(this.size) / 100.0 t := mathgl.Translate3D(curTotWidth, 0, 0).Mul4x1(vertex) t = mathgl.Scale3D(scale, scale, 1).Mul4x1(t) return t }
func (t *Transform2D) Update(dt float32) { /* Update transform */ rad := t.Rotation * math.Pi / 180.0 rotation := mgl.AnglesToQuat(0, 0, rad, mgl.XYZ).Mat4() scaling := mgl.Scale3D(t.Scale[0], t.Scale[1], 1) translation := mgl.Translate3D(t.Position[0], t.Position[1], t.Position[2]) /* New transform matrix: S * R * T */ t.Matrix = scaling.Mul4(rotation.Mul4(translation)) }
func (t *Text) AddScale(s float32) (changed bool) { if s < 0 && t.Scale <= t.ScaleMin { return } if s > 0 && t.Scale >= t.ScaleMax { return } changed = true t.Scale += s t.scaleMatrix = mgl32.Scale3D(t.Scale, t.Scale, t.Scale) return }
func (c Context) DrawRectangle(x, y, w, h float32, color Color) { gl.UseProgram(c.program) model := mgl32.Translate3D(x, y, 0).Mul4(mgl32.Scale3D(w, h, 0)) modelUniform := gl.GetUniformLocation(c.program, gl.Str("model\x00")) gl.UniformMatrix4fv(modelUniform, 1, false, &model[0]) colorArray := []float32{color.B, color.G, color.R} colorUniform := gl.GetUniformLocation(c.program, gl.Str("color\x00")) gl.Uniform4fv(colorUniform, 1, &colorArray[0]) gl.DrawArrays(gl.TRIANGLES, 0, 6) }
func (k PianoKey) GetMtx() mgl32.Mat4 { axis := mgl32.Vec3{1, 0, 0} keyLen := float32(2.0) if !k.white { keyLen = 1.0 } modelMtx := mgl32.Ident4() modelMtx = modelMtx.Mul4(mgl32.Translate3D(k.Pos[0], k.Pos[1], k.Pos[2]-2)) modelMtx = modelMtx.Mul4(mgl32.HomogRotate3D(k.Angle, axis)) modelMtx = modelMtx.Mul4(mgl32.Translate3D(0, 0, keyLen)) modelMtx = modelMtx.Mul4(mgl32.Scale3D(0.5, 0.5, keyLen)) return modelMtx }
// Render renders the bitmap with the center at given position func (renderable *SimpleBitmapRenderable) Render(context *RenderContext, icons []PlacedIcon) { gl := renderable.gl renderable.withShader(func() { renderable.setMatrix(renderable.viewMatrixUniform, context.ViewMatrix()) renderable.setMatrix(renderable.projectionMatrixUniform, context.ProjectionMatrix()) gl.EnableVertexAttribArray(uint32(renderable.vertexPositionAttrib)) gl.BindBuffer(opengl.ARRAY_BUFFER, renderable.vertexPositionBuffer) gl.VertexAttribOffset(uint32(renderable.vertexPositionAttrib), 3, opengl.FLOAT, false, 0, 0) gl.EnableVertexAttribArray(uint32(renderable.uvPositionAttrib)) gl.BindBuffer(opengl.ARRAY_BUFFER, renderable.uvPositionBuffer) gl.VertexAttribOffset(uint32(renderable.uvPositionAttrib), 3, opengl.FLOAT, false, 0, 0) textureUnit := int32(0) gl.ActiveTexture(opengl.TEXTURE0 + uint32(textureUnit)) gl.BindTexture(opengl.TEXTURE_2D, renderable.paletteTexture.Handle()) gl.Uniform1i(renderable.paletteUniform, textureUnit) textureUnit = 1 gl.ActiveTexture(opengl.TEXTURE0 + uint32(textureUnit)) gl.Uniform1i(renderable.bitmapUniform, textureUnit) for _, icon := range icons { x, y := icon.Center() u, v := icon.Icon().UV() width, height := renderable.limitedSize(icon) modelMatrix := mgl.Ident4(). Mul4(mgl.Translate3D(x, y, 0.0)). Mul4(mgl.Scale3D(width, height, 1.0)) renderable.setMatrix(renderable.modelMatrixUniform, &modelMatrix) var uv = []float32{ 0.0, 0.0, 0.0, u, 0.0, 0.0, u, v, 0.0, u, v, 0.0, 0.0, v, 0.0, 0.0, 0.0, 0.0} gl.BindBuffer(opengl.ARRAY_BUFFER, renderable.uvPositionBuffer) gl.BufferData(opengl.ARRAY_BUFFER, len(uv)*4, uv, opengl.STATIC_DRAW) gl.BindTexture(opengl.TEXTURE_2D, icon.Icon().Handle()) gl.DrawArrays(opengl.TRIANGLES, 0, 6) } gl.BindTexture(opengl.TEXTURE_2D, 0) }) }
// NewTextureRenderable returns a new instance of a texture renderable func NewTextureRenderable(gl opengl.OpenGl, positionX, positionY float32, displaySize float32, paletteTexture graphics.Texture, bitmapTexture graphics.Texture) *TextureRenderable { vertexShader, err1 := opengl.CompileNewShader(gl, opengl.VERTEX_SHADER, textureVertexShaderSource) defer gl.DeleteShader(vertexShader) fragmentShader, err2 := opengl.CompileNewShader(gl, opengl.FRAGMENT_SHADER, textureFragmentShaderSource) defer gl.DeleteShader(fragmentShader) program, _ := opengl.LinkNewProgram(gl, vertexShader, fragmentShader) if err1 != nil { fmt.Fprintf(os.Stderr, "Failed to compile shader 1:\n", err1) } if err2 != nil { fmt.Fprintf(os.Stderr, "Failed to compile shader 2:\n", err2) } renderable := &TextureRenderable{ gl: gl, program: program, modelMatrix: mgl.Ident4(). Mul4(mgl.Translate3D(positionX, positionY, 0.0)). Mul4(mgl.Scale3D(displaySize, displaySize, 1.0)), vertexArrayObject: gl.GenVertexArrays(1)[0], vertexPositionBuffer: gl.GenBuffers(1)[0], vertexPositionAttrib: gl.GetAttribLocation(program, "vertexPosition"), modelMatrixUniform: gl.GetUniformLocation(program, "modelMatrix"), viewMatrixUniform: gl.GetUniformLocation(program, "viewMatrix"), projectionMatrixUniform: gl.GetUniformLocation(program, "projectionMatrix"), paletteTexture: paletteTexture, paletteUniform: gl.GetUniformLocation(program, "palette"), bitmapTexture: bitmapTexture, bitmapUniform: gl.GetUniformLocation(program, "bitmap")} renderable.withShader(func() { gl.BindBuffer(opengl.ARRAY_BUFFER, renderable.vertexPositionBuffer) limit := float32(1.0) var vertices = []float32{ 0.0, 0.0, 0.0, limit, 0.0, 0.0, limit, limit, 0.0, limit, limit, 0.0, 0.0, limit, 0.0, 0.0, 0.0, 0.0} gl.BufferData(opengl.ARRAY_BUFFER, len(vertices)*4, vertices, opengl.STATIC_DRAW) }) return renderable }
func NewFloor(shader Shader, reflected ...Drawable) Drawable { floor := NewStaticShape() floor.vertices = floorVertices floor.normals = floorNormals floor.Buffer() flipped := mgl.Scale3D(1, -1, 1) return &Floor{ Node: Node{ Shape: floor, transform: &flipped, shader: shader, }, reflected: reflected, } }
func (this *Transform) GetUpdatedModel() mathgl.Mat4 { Model := this.model Model = Model.Mul4(mathgl.Translate3D(float32(this.X), float32(this.Y), float32(this.Z))) // Model = Model.Mul4(mathgl.HomogRotate3DZ(float32(s.rot))) // Model = Model.Mul4(mathgl.HomogRotate3D(s.Rot, mathgl.Vec3{s.XR, s.YR, s.ZR})) // Euler rotation is easy.. no quaternions yet.. what a pain. Model = Model.Mul4(mathgl.Rotate3DX(this.XR * this.Rot).Mat4()) Model = Model.Mul4(mathgl.Rotate3DY(this.YR * this.Rot).Mat4()) Model = Model.Mul4(mathgl.Rotate3DZ(this.ZR * this.Rot).Mat4()) Model = Model.Mul4(mathgl.Scale3D(float32(this.XS), float32(this.YS), float32(this.ZS))) return Model }
func (i *Instance) GetModel() mgl32.Mat4 { if i.dirty { var model mgl32.Mat4 model = mgl32.Translate3D( i.position.X(), i.position.Y(), i.position.Z(), ) model = model.Mul4(mgl32.HomogRotate3DZ(mgl32.DegToRad(i.rotation))) model = model.Mul4(mgl32.Scale3D(i.scale.X(), i.scale.Y(), i.scale.Z())) i.model = model i.dirty = false } return i.model }
// DrawFrame will draw the sprite in the x,y and z with the specified frame from a spritesheet func (sprite *Sprite) DrawFrame(x float32, y float32, z float32, scale float32, frame int) { model := mgl32.Translate3D(x, y, z) model = model.Mul4(mgl32.Scale3D(scale, scale, 1)) // remember this is in radians! // model = model.Mul4(mgl32.HomogRotate3D(mgl32.DegToRad(90), mgl32.Vec3{0, 0, 1})) if shader := shader.GetActive(); shader != nil { gl.UniformMatrix4fv(shader.Model, 1, false, &model[0]) } gl.BindVertexArray(sprite.vao) sprite.image.Bind() gl.DrawArrays(gl.TRIANGLES, int32(frame*6), 6) }
// Scale scales the coordinate system in two dimensions. By default the coordinate system /// in amore corresponds to the display pixels in horizontal and vertical directions // one-to-one, and the x-axis increases towards the right while the y-axis increases // downwards. Scaling the coordinate system changes this relation. After scaling by // sx and sy, all coordinates are treated as if they were multiplied by sx and sy. // Every result of a drawing operation is also correspondingly scaled, so scaling by // (2, 2) for example would mean making everything twice as large in both x- and y-directions. Scaling by a negative value flips the coordinate system in the corresponding direction, which also means everything will be drawn flipped or upside down, or both. Scaling by zero is not a useful operation. // Scale and translate are not commutative operations, therefore, calling them // in different orders will change the outcome. Scaling lasts until drawing completes func Scale(args ...float32) { if args == nil || len(args) == 0 { panic("not enough params passed to scale call") } var sx, sy float32 sx = args[0] if len(args) > 1 { sy = args[1] } else { sy = sx } gl_state.viewStack.LeftMul(mgl32.Scale3D(sx, sy, 1)) states.back().pixelSize *= (2.0 / (mgl32.Abs(sx) + mgl32.Abs(sy))) }
func TestReseed(t *testing.T) { stack := NewTransformStack() scale := mgl32.Scale3D(2, 2, 2) rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90)) trans := mgl32.Translate3D(4, 5, 6) stack.Push(trans) stack.Push(rot) stack.Push(scale) trans2 := mgl32.Translate3D(1, 2, 3) err := stack.Reseed(1, trans2) if err != nil { t.Fatalf("Rebase returned error when it should not %v", err) } if !stack.Peek().ApproxEqualThreshold(trans2.Mul4(rot).Mul4(scale), 1e-4) { t.Fatalf("Rebase does not remultiply correctly. Got\n %v expected\n %v. (Previous state:\n %v)", stack.Peek(), trans2.Mul4(rot).Mul4(scale), trans.Mul4(rot).Mul4(scale)) } }
func TestRebase(t *testing.T) { stack := NewTransformStack() stack2 := NewTransformStack() scale := mgl32.Scale3D(2, 2, 2) rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90)) trans := mgl32.Translate3D(4, 5, 6) trans2 := mgl32.Translate3D(1, 2, 3) stack.Push(trans) stack.Push(rot) stack2.Push(trans2) stack2.Push(scale) out, _ := Rebase(stack2, 1, stack) if !out.Peek().ApproxEqualThreshold(trans.Mul4(rot).Mul4(trans2).Mul4(scale), 1e-4) { t.Log("\n", out) t.Errorf("Rebase unsuccessful. Got\n %v, expected\n %v", out.Peek(), trans.Mul4(rot).Mul4(trans2).Mul4(scale)) } }
// Render renders the highlight. func (highlighter *BasicHighlighter) Render(context *RenderContext, areas []Area) { gl := highlighter.gl highlighter.withShader(func() { highlighter.setMatrix(highlighter.viewMatrixUniform, context.ViewMatrix()) highlighter.setMatrix(highlighter.projectionMatrixUniform, context.ProjectionMatrix()) gl.BindBuffer(opengl.ARRAY_BUFFER, highlighter.vertexPositionBuffer) gl.VertexAttribOffset(uint32(highlighter.vertexPositionAttrib), 3, opengl.FLOAT, false, 0, 0) for _, area := range areas { x, y := area.Center() width, height := area.Size() modelMatrix := mgl.Ident4(). Mul4(mgl.Translate3D(x, y, 0.0)). Mul4(mgl.Scale3D(width, height, 1.0)) highlighter.setMatrix(highlighter.modelMatrixUniform, &modelMatrix) gl.DrawArrays(opengl.TRIANGLES, 0, 6) } }) }
func ExampleReseed() { stack := NewTransformStack() scale := mgl32.Scale3D(2, 2, 2) rot := mgl32.HomogRotate3DY(mgl32.DegToRad(90)) trans := mgl32.Translate3D(4, 5, 6) stack.Push(trans) stack.Push(rot) stack.Push(scale) fmt.Println("Initial state:\n", stack.Peek()) trans2 := mgl32.Translate3D(1, 2, 3) err := stack.Reseed(1, trans2) if err == nil { panic("Rebase failed") } fmt.Println("After rebase:\n", stack.Peek()) fmt.Println("Should be:\n", trans2.Mul4(rot).Mul4(scale)) }
// NewTextRenderable returns a new instance of a text renderable func NewTextRenderable(gl opengl.OpenGl, positionX, positionY float32, displaySize float32, paletteTexture graphics.Texture) *TextRenderable { vertexShader, err1 := opengl.CompileNewShader(gl, opengl.VERTEX_SHADER, textVertexShaderSource) defer gl.DeleteShader(vertexShader) fragmentShader, err2 := opengl.CompileNewShader(gl, opengl.FRAGMENT_SHADER, textFragmentShaderSource) defer gl.DeleteShader(fragmentShader) program, _ := opengl.LinkNewProgram(gl, vertexShader, fragmentShader) if err1 != nil { fmt.Fprintf(os.Stderr, "Failed to compile shader 1:\n", err1) } if err2 != nil { fmt.Fprintf(os.Stderr, "Failed to compile shader 2:\n", err2) } renderable := &TextRenderable{ gl: gl, program: program, modelMatrix: mgl.Ident4(). Mul4(mgl.Translate3D(positionX, positionY, 0.0)). Mul4(mgl.Scale3D(displaySize, displaySize, 1.0)), vertexArrayObject: gl.GenVertexArrays(1)[0], vertexPositionBuffer: gl.GenBuffers(1)[0], vertexPositionAttrib: gl.GetAttribLocation(program, "vertexPosition"), uvPositionBuffer: gl.GenBuffers(1)[0], uvPositionAttrib: gl.GetAttribLocation(program, "uvPosition"), modelMatrixUniform: gl.GetUniformLocation(program, "modelMatrix"), viewMatrixUniform: gl.GetUniformLocation(program, "viewMatrix"), projectionMatrixUniform: gl.GetUniformLocation(program, "projectionMatrix"), paletteTexture: paletteTexture, paletteUniform: gl.GetUniformLocation(program, "palette"), bitmapUniform: gl.GetUniformLocation(program, "bitmap"), text: ""} return renderable }
func (cam *LimitedCamera) updateViewMatrix() { scaleFactor := cam.scaleFactor() cam.viewMatrix = mgl.Ident4(). Mul4(mgl.Scale3D(scaleFactor, scaleFactor, 1.0)). Mul4(mgl.Translate3D(cam.viewOffsetX, cam.viewOffsetY, 0)) }
func programLoop(window *win.Window) error { // the linked shader program determines how the data will be rendered vertShader, err := gfx.NewShaderFromFile("shaders/phong.vert", gl.VERTEX_SHADER) if err != nil { return err } fragShader, err := gfx.NewShaderFromFile("shaders/phong.frag", gl.FRAGMENT_SHADER) if err != nil { return err } program, err := gfx.NewProgram(vertShader, fragShader) if err != nil { return err } defer program.Delete() lightFragShader, err := gfx.NewShaderFromFile("shaders/light.frag", gl.FRAGMENT_SHADER) if err != nil { return err } // special shader program so that lights themselves are not affected by lighting lightProgram, err := gfx.NewProgram(vertShader, lightFragShader) if err != nil { return err } VAO := createVAO(cubeVertices, nil) lightVAO := createVAO(cubeVertices, nil) // ensure that triangles that are "behind" others do not draw over top of them gl.Enable(gl.DEPTH_TEST) camera := cam.NewFpsCamera(mgl32.Vec3{0, 0, 3}, mgl32.Vec3{0, 1, 0}, -90, 0, window.InputManager()) for !window.ShouldClose() { // swaps in last buffer, polls for window events, and generally sets up for a new render frame window.StartFrame() // update camera position and direction from input evevnts camera.Update(window.SinceLastFrame()) // background color gl.ClearColor(0, 0, 0, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) // depth buffer needed for DEPTH_TEST // cube rotation matrices rotateX := (mgl32.Rotate3DX(mgl32.DegToRad(-45 * float32(glfw.GetTime())))) rotateY := (mgl32.Rotate3DY(mgl32.DegToRad(-45 * float32(glfw.GetTime())))) rotateZ := (mgl32.Rotate3DZ(mgl32.DegToRad(-45 * float32(glfw.GetTime())))) // creates perspective fov := float32(60.0) projectTransform := mgl32.Perspective(mgl32.DegToRad(fov), float32(window.Width())/float32(window.Height()), 0.1, 100.0) camTransform := camera.GetTransform() lightPos := mgl32.Vec3{0.6, 1, 0.1} lightTransform := mgl32.Translate3D(lightPos.X(), lightPos.Y(), lightPos.Z()).Mul4( mgl32.Scale3D(0.2, 0.2, 0.2)) program.Use() gl.UniformMatrix4fv(program.GetUniformLocation("view"), 1, false, &camTransform[0]) gl.UniformMatrix4fv(program.GetUniformLocation("project"), 1, false, &projectTransform[0]) gl.BindVertexArray(VAO) // draw each cube after all coordinate system transforms are bound // obj is colored, light is white gl.Uniform3f(program.GetUniformLocation("material.ambient"), 1.0, 0.5, 0.31) gl.Uniform3f(program.GetUniformLocation("material.diffuse"), 1.0, 0.5, 0.31) gl.Uniform3f(program.GetUniformLocation("material.specular"), 0.5, 0.5, 0.5) gl.Uniform1f(program.GetUniformLocation("material.shininess"), 32.0) lightColor := mgl32.Vec3{ float32(math.Sin(glfw.GetTime() * 1)), float32(math.Sin(glfw.GetTime() * 0.35)), float32(math.Sin(glfw.GetTime() * 0.65)), } diffuseColor := mgl32.Vec3{ 0.5 * lightColor[0], 0.5 * lightColor[1], 0.5 * lightColor[2], } ambientColor := mgl32.Vec3{ 0.2 * lightColor[0], 0.2 * lightColor[1], 0.2 * lightColor[2], } gl.Uniform3f(program.GetUniformLocation("light.ambient"), ambientColor[0], ambientColor[1], ambientColor[2]) gl.Uniform3f(program.GetUniformLocation("light.diffuse"), diffuseColor[0], diffuseColor[1], diffuseColor[2]) gl.Uniform3f(program.GetUniformLocation("light.specular"), 1.0, 1.0, 1.0) gl.Uniform3f(program.GetUniformLocation("light.position"), lightPos.X(), lightPos.Y(), lightPos.Z()) for _, pos := range cubePositions { // turn the cubes into rectangular prisms for more fun worldTranslate := mgl32.Translate3D(pos[0], pos[1], pos[2]) worldTransform := worldTranslate.Mul4( rotateX.Mul3(rotateY).Mul3(rotateZ).Mat4(), ) gl.UniformMatrix4fv(program.GetUniformLocation("model"), 1, false, &worldTransform[0]) gl.DrawArrays(gl.TRIANGLES, 0, 36) } gl.BindVertexArray(0) // Draw the light obj after the other boxes using its separate shader program // this means that we must re-bind any uniforms lightProgram.Use() gl.BindVertexArray(lightVAO) gl.UniformMatrix4fv(lightProgram.GetUniformLocation("model"), 1, false, &lightTransform[0]) gl.UniformMatrix4fv(lightProgram.GetUniformLocation("view"), 1, false, &camTransform[0]) gl.UniformMatrix4fv(lightProgram.GetUniformLocation("project"), 1, false, &projectTransform[0]) gl.DrawArrays(gl.TRIANGLES, 0, 36) gl.BindVertexArray(0) // end of draw loop } return nil }
func (cube *Cube) Scale(scaleX, scaleY, scaleZ float32) { cube.Model = cube.Model.Mul4(mgl32.Scale3D(scaleX, scaleY, scaleZ)) }
// Draw draws a single frame func Draw(width, height int, delta float64) { tickAnimatedTextures(delta) frameID++ sync: for { select { case f := <-syncChan: f() default: break sync } } // Only update the viewport if the window was resized if lastHeight != height || lastWidth != width || lastFOV != FOV.Value() { lastWidth = width lastHeight = height lastFOV = FOV.Value() perspectiveMatrix = mgl32.Perspective( (math.Pi/180)*float32(lastFOV), float32(width)/float32(height), 0.1, 500.0, ) gl.Viewport(0, 0, width, height) frustum.SetPerspective( (math.Pi/180)*float32(lastFOV), float32(width)/float32(height), 0.1, 500.0, ) initTrans() } mainFramebuffer.Bind() gl.Enable(gl.Multisample) gl.ActiveTexture(0) glTexture.Bind(gl.Texture2DArray) gl.ClearColor(ClearColour.R, ClearColour.G, ClearColour.B, 1.0) gl.Clear(gl.ColorBufferBit | gl.DepthBufferBit) chunkProgram.Use() viewVector = mgl32.Vec3{ float32(math.Cos(Camera.Yaw-math.Pi/2) * -math.Cos(Camera.Pitch)), float32(-math.Sin(Camera.Pitch)), float32(-math.Sin(Camera.Yaw-math.Pi/2) * -math.Cos(Camera.Pitch)), } cam := mgl32.Vec3{-float32(Camera.X), -float32(Camera.Y), float32(Camera.Z)} cameraMatrix = mgl32.LookAtV( cam, cam.Add(mgl32.Vec3{-viewVector.X(), -viewVector.Y(), viewVector.Z()}), mgl32.Vec3{0, -1, 0}, ) cameraMatrix = cameraMatrix.Mul4(mgl32.Scale3D(-1.0, 1.0, 1.0)) frustum.SetCamera( cam, cam.Add(mgl32.Vec3{-viewVector.X(), -viewVector.Y(), viewVector.Z()}), mgl32.Vec3{0, -1, 0}, ) shaderChunk.PerspectiveMatrix.Matrix4(&perspectiveMatrix) shaderChunk.CameraMatrix.Matrix4(&cameraMatrix) shaderChunk.Texture.Int(0) shaderChunk.LightLevel.Float(LightLevel) shaderChunk.SkyOffset.Float(SkyOffset) chunkPos := position{ X: int(Camera.X) >> 4, Y: int(Camera.Y) >> 4, Z: int(Camera.Z) >> 4, } nearestBuffer = buffers[chunkPos] for _, dir := range direction.Values { validDirs[dir] = viewVector.Dot(dir.AsVec()) > -0.8 } renderOrder = renderOrder[:0] renderBuffer(nearestBuffer, chunkPos, direction.Invalid, delta) drawLines() drawModels() clouds.tick(delta) chunkProgramT.Use() shaderChunkT.PerspectiveMatrix.Matrix4(&perspectiveMatrix) shaderChunkT.CameraMatrix.Matrix4(&cameraMatrix) shaderChunkT.Texture.Int(0) shaderChunkT.LightLevel.Float(LightLevel) shaderChunkT.SkyOffset.Float(SkyOffset) // Copy the depth buffer mainFramebuffer.BindRead() transFramebuffer.BindDraw() gl.BlitFramebuffer( 0, 0, lastWidth, lastHeight, 0, 0, lastWidth, lastHeight, gl.DepthBufferBit, gl.Nearest, ) gl.Enable(gl.Blend) gl.DepthMask(false) transFramebuffer.Bind() gl.ClearColor(0, 0, 0, 1) gl.Clear(gl.ColorBufferBit) gl.ClearBuffer(gl.Color, 0, []float32{0, 0, 0, 1}) gl.ClearBuffer(gl.Color, 1, []float32{0, 0, 0, 0}) gl.BlendFuncSeparate(gl.OneFactor, gl.OneFactor, gl.ZeroFactor, gl.OneMinusSrcAlpha) for _, chunk := range renderOrder { if chunk.countT > 0 && chunk.bufferT.IsValid() { shaderChunkT.Offset.Int3(chunk.X, chunk.Y*4096-chunk.Y*int(4096*(1-chunk.progress)), chunk.Z) chunk.arrayT.Bind() gl.DrawElements(gl.Triangles, chunk.countT, elementBufferType, 0) } } gl.UnbindFramebuffer() gl.Disable(gl.DepthTest) gl.Clear(gl.ColorBufferBit) gl.Disable(gl.Blend) transDraw() gl.Enable(gl.DepthTest) gl.DepthMask(true) gl.BlendFunc(gl.SrcAlpha, gl.OneMinusSrcAlpha) gl.Disable(gl.Multisample) drawUI() if debugFramebuffers.Value() { gl.Enable(gl.Multisample) blitBuffers() gl.Disable(gl.Multisample) } }
//SetScale reset this transform to represent only the scaling transform of `amount` //I do not allow non-uniform scaling to prevent ending up with matrices without an inverse. func (t *Transform) SetScale(amount float32) { t.LocalToWorld = glm.Scale3D(amount, amount, amount) }
//Scale add a scaling operation to the currently stored transform. //I do not allow non-uniform scaling to prevent ending up with matrices without an inverse. func (t *Transform) Scale(amount float32) { t.LocalToWorld = t.LocalToWorld.Mul4(glm.Scale3D(amount, amount, amount)) }