Page MenuHomePhorge

Rendering
Updated 244 Days AgoPublic

NOTE: This is a work in progress.

At Echo's core there is a Kernel that updates Tasks. In order to get work done you create tasks which will be periodically updated. Rendering to the screen is one such task. Unlike other engines, which might have a strict update then render loop, Echo decentralises rendering. This allows you to decide when rendering occurs.

As far as Echo, or more specifically a Kernel` is concerned, rendering is just a job for another Task.

Rendering is performed by a Renderer which is a Task. When the Renderer tasks updates it renders a Scene through a Camera to a RenderTarget with the defined Viewport set.

You can set up multiple Renderer objects to perform rendering to multiple views on the same RenderTarget, this would allow you to perform split screen rendering. You can also set up multiple renderers might be to render the same scene to a different RenderTarget such as a texture or second display. Or the same scene through a different camera to a different render target.

If you are rendering two view ports to the same RenderTarget using two Renderer objects directly you will find that one will flicker. This is because a Renderer by itself is designed to perform pre and post rendering operations, such as clearing the screen and swapping the screen buffer. In order to render multiple viewports to the same target you will need to disable these pre and post operations on each Renderer depending on the order they should be rendered. To make this job simpler Echo provides a MultiRenderer class which you can use to create Renderer objects for the same target.

dot {{{
	digraph A {
		fontname = "Bitstream Vera Sans"
		fontsize = 8
		
		node [
			fontname = "Bitstream Vera Sans"
			fontsize = 8
			shape = "box"
			]
		
		edge [
			headlabel = ""
			taillabel=""
			arrowhead="odiamond"
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
	
		Renderer->RenderTarget
       		Renderer->Viewport
       		Renderer->Camera
       		Camera->Scene
       		MultiRenderer->Renderer

		edge [
			arrowhead = "empty"
			headlabel = ""
			taillabel=""
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
		PlatformRenderTarget->RenderTarget

		edge [
			dir="back"
			arrowhead = "empty"
			arrowtail = "empty"
			headlabel = ""
			taillabel=""
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
		Task->Renderer
		Task->MultiRenderer
	}
}}}

When a Camera renders a Scene the Scene will build a render queue. The render queue of SceneRenderables which provide a position and bounds that can be used for sorting. The queue is sorted and then rendered in the appropriate order.

Most of the time you'll find that SceneRenderable objects are actually SceneEntity objects. SceneEntity objects are simple SceneRenderable objects that have a Mesh. The Mesh can be loaded from a file, a specialised Mesh object such as a TextMesh, or can be created manually. The Mesh is rendered by the SceneEntity when the SceneEntity is rendered in the Scene.

dot {{{
	digraph A {
		fontname = "Bitstream Vera Sans"
		fontsize = 8
		
		node [
			fontname = "Bitstream Vera Sans"
			fontsize = 8
			shape = "box"
			]
			
		N [ label = "Node"]
		
		edge [
			headlabel = ""
			taillabel=""
			arrowhead="odiamond"
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
	
       		Scene->SceneRenderable
       		SceneEntity->Mesh

		edge [
			arrowhead = "empty"
			headlabel = ""
			taillabel=""
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
       		SceneEntity->SceneRenderable
       		SceneRenderable->N
       		SceneRenderable->Renderable
       		Mesh->Renderable
	}
}}}

There are a number of more useful specialised SceneEntity types as well as some specialised Mesh types that will construct Mesh objects as needed.

dot {{{
	digraph A {
		fontname = "Bitstream Vera Sans"
		fontsize = 8
		
		node [
			fontname = "Bitstream Vera Sans"
			fontsize = 8
			shape = "box"
			]
			
		Element [ label="GUI::Element" ]
		
		edge [
			headlabel = ""
			taillabel=""
			arrowhead="odiamond"
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
	
		edge [
			arrowhead = "empty"
			headlabel = ""
			taillabel=""
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
       		TextEntity->SceneEntity
       		TextMesh->Mesh
       		Element->SceneEntity
       		Sprite->SceneEntity
	}
}}}

Most of the time we are just rendering a Mesh object to a RenderTarget. The way that Mesh is displayed is determined by its Material.

Materials are made up of a number of passes. Each pass is essentially a render operation. A RenderPass defines the textures that will be rendered along with other properties such whether or not the object will be affected by lighting and how it should be blended with the existing scene.

NOTE: A RenderPass may also define a shader program that overrides how the object is displayed. Shader programs are really flexible but may not be supported on all platforms. At the very minimum Echo implements a consistent "simple" render pipeline through materials.

The textures are defined as TextureUnits which specify which image (the texture) will be used for rendering as well as how the texture will be blended with with other texture units. This topic can be quite complicated especially when we are using shaders. See this document for more information.

Materials can be defined in a file or through code. Defining materials in files means much less code is required. For more information on materials see this document.

dot {{{
	digraph A {
		fontname = "Bitstream Vera Sans"
		fontsize = 8
		
		node [
			fontname = "Bitstream Vera Sans"
			fontsize = 8
			shape = "box"
			]

		edge [
			headlabel = "1"
			taillabel="1"
			arrowhead="odiamond"
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
		
		Mesh->Material
		
		edge [
			headlabel = "*"
			taillabel="1"
			arrowhead="diamond"
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
		
		Material->RenderPass
		RenderPass->TextureUnit
	
		edge [
			arrowhead = "empty"
			headlabel = ""
			taillabel=""
			fontname = "Bitstream Vera Sans"
			fontsize = 8
		]
	}
}}}
Last Author
0xseantasker
Last Edited
Apr 3 2024, 11:26 PM

Event Timeline

0xseantasker edited the content of this document. (Show Details)
0xseantasker changed the visibility from "All Users" to "Public (No Login Required)".Mar 6 2019, 5:21 PM