func drawModels() { if len(modelState.models) == 0 { return } m := 4 if modelState.indexType == gl.UnsignedShort { m = 2 } gl.Enable(gl.Blend) offsetBuf := make([]uintptr, 10) for _, c := range modelState.models { c.program.Use() c.shader.Texture.Int(0) c.shader.PerspectiveMatrix.Matrix4(&perspectiveMatrix) c.shader.CameraMatrix.Matrix4(&cameraMatrix) c.shader.SkyOffset.Float(SkyOffset) c.shader.LightLevel.Float(LightLevel) gl.BlendFunc(c.blendS, c.blendD) for _, mdl := range c.models { if mdl.Radius != 0 && !frustum.IsSphereInside(mdl.X, mdl.Y, mdl.Z, mdl.Radius) { continue } mdl.array.Bind() c.shader.Lighting.Float2(mdl.BlockLight, mdl.SkyLight) if len(mdl.counts) > 1 { copy(offsetBuf, mdl.offsets) for i := range mdl.offsets { offsetBuf[i] *= uintptr(m) } c.shader.ModelMatrix.Matrix4Multi(mdl.Matrix) c.shader.ColorMul.FloatMutliRaw(mdl.Colors, len(mdl.Colors)) gl.MultiDrawElements(gl.Triangles, mdl.counts, modelState.indexType, offsetBuf[:len(mdl.offsets)]) } else { c.shader.ModelMatrix.Matrix4Multi(mdl.Matrix) c.shader.ColorMul.FloatMutliRaw(mdl.Colors, len(mdl.Colors)) gl.DrawElements(gl.Triangles, int(mdl.counts[0]), modelState.indexType, int(mdl.offsets[0])*m) } } } gl.Disable(gl.Blend) }
func drawLines() { if lineState.count > 0 { gl.Enable(gl.Blend) lineState.program.Use() lineState.shader.PerspectiveMatrix.Matrix4(&perspectiveMatrix) lineState.shader.CameraMatrix.Matrix4(&cameraMatrix) lineState.array.Bind() lineState.buffer.Bind(gl.ArrayBuffer) if len(lineState.data) > lineState.prevSize { lineState.prevSize = len(lineState.data) lineState.buffer.Data(lineState.data, gl.DynamicDraw) } else { target := lineState.buffer.Map(gl.WriteOnly, len(lineState.data)) copy(target, lineState.data) lineState.buffer.Unmap() } gl.DrawArrays(gl.Triangles, 0, lineState.count) lineState.count = 0 lineState.data = lineState.data[:0] gl.Disable(gl.Blend) } }
func drawUI() { // Prevent clipping with the world gl.Clear(gl.DepthBufferBit) gl.DepthFunc(gl.LessOrEqual) gl.Enable(gl.Blend) uiState.program.Use() uiState.shader.Texture.Int(0) if uiState.count > 0 { uiState.array.Bind() if uiState.maxIndex < uiState.count { var data []byte data, uiState.indexType = genElementBuffer(uiState.count) uiState.indexBuffer.Bind(gl.ElementArrayBuffer) uiState.indexBuffer.Data(data, gl.DynamicDraw) uiState.maxIndex = uiState.count } uiState.shader.ScreenSize.Float2(float32(lastWidth), float32(lastHeight)) uiState.buffer.Bind(gl.ArrayBuffer) if len(uiState.data) > uiState.prevSize { uiState.prevSize = len(uiState.data) uiState.buffer.Data(uiState.data, gl.StreamDraw) } else { target := uiState.buffer.Map(gl.WriteOnly, len(uiState.data)) copy(target, uiState.data) uiState.buffer.Unmap() } gl.DrawElements(gl.Triangles, uiState.count, uiState.indexType, 0) } gl.Disable(gl.Blend) gl.DepthFunc(gl.LessOrEqual) uiState.count = 0 uiState.data = uiState.data[:0] }
// 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) } }