Exemple #1
0
func (r *Renderer) useState(obj *gfx.Object, c *gfx.Camera) {
	// Use object state.
	r.stateColorWrite(obj.WriteRed, obj.WriteGreen, obj.WriteBlue, obj.WriteAlpha)
	r.stateDithering(obj.Dithering)
	r.stateStencilTest(obj.StencilTest)
	r.stateStencilOp(obj.StencilFront, obj.StencilBack)
	r.stateStencilFunc(obj.StencilFront, obj.StencilBack)
	r.stateStencilMask(obj.StencilFront.WriteMask, obj.StencilBack.WriteMask)
	r.stateDepthFunc(obj.DepthCmp)
	r.stateDepthTest(obj.DepthTest)
	r.stateDepthWrite(obj.DepthWrite)
	r.stateFaceCulling(obj.FaceCulling)

	// Consider rebuilding the object's cached matrices, if needed.
	nativeObj := obj.NativeObject.(nativeObject)
	if nativeObj.needRebuild(obj, c) {
		// Rebuild cached matrices.
		nativeObj = nativeObj.rebuild(obj, c)
	}
	obj.NativeObject = nativeObj

	// Set alpha mode.
	r.stateAlphaToCoverage(obj.AlphaMode == gfx.AlphaToCoverage)
	r.stateBlend(obj.AlphaMode == gfx.AlphaBlend)
	if obj.AlphaMode == gfx.AlphaBlend {
		r.stateBlendColor(obj.Blend.Color)
		r.stateBlendFuncSeparate(obj.Blend)
		r.stateBlendEquationSeparate(obj.Blend)
	}

	// Begin occlusion query.
	obj.NativeObject = r.beginQuery(obj, nativeObj)
}
Exemple #2
0
func (r *Renderer) clearState(obj *gfx.Object) {
	// End occlusion query.
	obj.NativeObject = r.endQuery(obj, obj.NativeObject.(nativeObject))

	// Use no texture.
	r.render.BindTexture(gl.TEXTURE_2D, 0)
	r.render.ActiveTexture(gl.TEXTURE0)
}
Exemple #3
0
// Implements gfx.Renderer interface.
func (r *Renderer) Draw(rect image.Rectangle, o *gfx.Object, c *gfx.Camera) {
	if o == nil {
		// Can't draw.
		return
	}

	lock := func() {
		o.Lock()
		if c != nil {
			c.Lock()
		}
	}

	unlock := func() {
		o.Unlock()
		if c != nil {
			c.Unlock()
		}
	}

	// Lock the object until we are completely done drawing it.
	lock()

	var (
		shaderLoaded   chan *gfx.Shader
		meshesLoaded   []chan *gfx.Mesh
		texturesLoaded []chan *gfx.Texture
	)

	// Begin loading shaders.
	for _, shader := range o.Shaders {
		if shader == nil {
			// Can't draw.
			unlock()
			return
		}
		shader.RLock()
		shaderNeedLoad := !shader.Loaded
		shaderCantDraw := !shader.CanDraw()
		shader.RUnlock()
		if shaderCantDraw {
			// Can't draw.
			unlock()
			return
		}
		if shaderNeedLoad {
			shaderLoaded = make(chan *gfx.Shader, 1)
			r.LoadShader(shader, shaderLoaded)
		}
	}

	for _, m := range o.Meshes {
		if m == nil {
			// Can't draw.
			unlock()
			return
		}
		m.RLock()
		meshNeedLoad := !m.Loaded || m.HasChanged()
		meshCantDraw := !m.CanDraw()
		m.RUnlock()
		if meshCantDraw {
			// Can't draw.
			unlock()
			return
		}
		if meshNeedLoad {
			ch := make(chan *gfx.Mesh, 1)
			r.LoadMesh(m, ch)
			meshesLoaded = append(meshesLoaded, ch)
		}
	}

	// Begin loading textures.
	for _, texSet := range o.Textures {
		for _, tex := range texSet {
			if tex == nil {
				// Can't draw.
				unlock()
				return
			}
			tex.RLock()
			texNeedLoad := !tex.Loaded
			texCantDraw := !tex.CanDraw()
			tex.RUnlock()
			if texCantDraw {
				// Can't draw.
				unlock()
				return
			}
			if texNeedLoad {
				ch := make(chan *gfx.Texture, 1)
				r.LoadTexture(tex, ch)
				texturesLoaded = append(texturesLoaded, ch)
			}
		}
	}

	// Wait for shader, meshes, and textures to finish loading.
	if shaderLoaded != nil {
		<-shaderLoaded
	}
	for _, load := range meshesLoaded {
		<-load
	}
	for _, load := range texturesLoaded {
		<-load
	}

	// Check if the now-loaded shaders might have errors.
	for _, shader := range o.Shaders {
		shader.RLock()
		shaderCantDraw := !shader.CanDraw()
		shader.RUnlock()
		if shaderCantDraw {
			// Can't draw.
			unlock()
			return
		}
	}

	// Must set at least an empty native object before Draw() returns.
	o.NativeObject = nativeObject{}

	// Ask the render loop to perform drawing.
	r.RenderExec <- func() bool {
		// Set global GL state.
		r.setGlobalState()

		// Update the scissor region (effects drawing).
		r.stateScissor(rect)

		// Use the object's state.
		r.useState(o, c)

		for meshIndex, mesh := range o.Meshes {
			shader := o.Shaders[meshIndex]
			var ns *nativeShader
			if shader.NativeShader != nil {
				ns = shader.NativeShader.(*nativeShader)
			}

			// Use the shader.
			r.useShader(ns, meshIndex, o)

			// Draw the mesh.
			r.drawMesh(ns, mesh)
		}

		// Clear the object's state.
		r.clearState(o)

		// Unlock the object now that we are done drawing it.
		unlock()

		// Yield for occlusion query results, if any are available.
		r.queryYield()

		return false
	}
}