# Write a simple renderer

**URL:** <https://discourse.libcinder.org/t/write-a-simple-renderer/594>\
**Category:** Uncategorized\
**Created:** [March 6, 2017, 9:15pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594 "2017-03-06T21:15:30Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 6, 2017, 9:15pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/1 "2017-03-06T21:15:30Z")

</div>

Hi,

I would like to write a renderer to improve my UI drawing code and am looking for some advice.  
I need to draw textures, text and shapes. My idea is to combine all these elements into one batch and just render it.

But am at a lost where to start.

I have a entity component system that defines my renderable objects. Text, Picture and Shape components.  
Text defines string, color and font to use. Picture defines the texture and color to use. Shape defines color and whether outline or filled shape. Each have a Transform component that defines scale, position & rotation.  
I have a Renderer class that gets all the renderable components in a scene and renders them.

Can i batch all these different objects into one batch? For example have 3 pictures, 2 Text and 4 Shapes (2 filled, 2 outline) in one batch.

Or do i have to split them into 3 different batches based on type(Text/Pictures/Shapes)?

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [March 6, 2017, 10:44pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/2 "2017-03-06T22:44:30Z")

</div>

A `Batch` combines a mesh and a shader and caches the buffer layout required to render the mesh. This speeds up rendering your content if the mesh and shader do not change (much). A `Batch` is drawn using a single draw call, but if you set things up correctly you can also use _instanced rendering_ to render the same mesh a thousand times using a single draw call.

Combining all the elements of your GUI into a single draw call is only possible if you carefully design your GUI. For example, you will have to combine all textures into a single, big texture, or a texture array. The primitive (points, lines, triangles) must be the same for all elements. The position of your vertices must be pre-transformed, or alternatively you’d have to store a list of matrices in a buffer and encode an index into this buffer in your vertices. In short: all your data must be prepared and uploaded before issuing your draw call.

In practice, you probably can not draw the full GUI in a single draw call. However, you can combine all text, because the glyphs are very similar and can therefor be combined more easily. If the shapes are similar, you can setup your pipeline to get ready for shape rendering once and then draw each shape or even combine them in a `VertBatch`.

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 7, 2017, 9:47pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/3 "2017-03-07T21:47:43Z")

</div>

Thanks paul, this is enough to get me started on a basic first version of my renderer.

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 8, 2017, 9:53pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/4 "2017-03-08T21:53:13Z")

</div>

Any samples on how to get texture arrays working?

I have tried declaring a uniform sampler2d array but it does not seem to pick anything but the first image which i suspect is default behaviour. I am binding my textures to different texture units using -\>bind(0), -\>bind(1)

I guess this might not work?  
i might have to declare a separate uniform sampler2d for each texture i bind, then set those every update using -\>uniform( “uTex0”, NUMBER\_OF\_TEXTURE\_UNIT );?

Here my batch setup code…

```
m_VboRef = ci::gl::Vbo::create(GL_ARRAY_BUFFER, m_aInfo.size() * sizeof(CInfo), m_aInfo.data(), GL_STATIC_DRAW);

	ci::geom::BufferLayout instanceDataLayout;
	instanceDataLayout.append(ci::geom::Attrib::CUSTOM_0, 2, sizeof(CInfo), offsetof(CInfo, m_vDstRect_getUpperLeft), 1 /* per instance*/);
	instanceDataLayout.append(ci::geom::Attrib::CUSTOM_1, 2, sizeof(CInfo), offsetof(CInfo, m_vDstRect_getSize), 1 /* per instance*/);
	instanceDataLayout.append(ci::geom::Attrib::CUSTOM_2, 2, sizeof(CInfo), offsetof(CInfo, m_vTexRect_getUpperLeft), 1 /* per instance*/);
	instanceDataLayout.append(ci::geom::Attrib::CUSTOM_3, 2, sizeof(CInfo), offsetof(CInfo, m_vTexRect_getSize), 1 /* per instance*/);
	instanceDataLayout.append(ci::geom::Attrib::CUSTOM_4, ci::geom::DataType::INTEGER, 1, sizeof(CInfo), offsetof(CInfo, m_iTextureUnit), 1 /* per instance*/);

	try {
		m_GlslProgRef = ci::gl::GlslProg::create(ci::app::loadAsset("shader.vert"), ci::app::loadAsset("shader.frag"));
	} catch (const std::exception &e) {
		ci::app::console() << "Failed to load object:" << e.what() << std::endl;
	}

	ci::Rectf rect(0.f, 0.f, 1.f, 1.f);
	m_MeshRef = ci::gl::VboMesh::create(ci::geom::Rect(rect));
	m_MeshRef->appendVbo(instanceDataLayout, m_VboRef);

	m_BatchRef = ci::gl::Batch::create(m_MeshRef, m_GlslProgRef, { { ci::geom::Attrib::CUSTOM_0, "vPositionOffset" }, { ci::geom::Attrib::CUSTOM_1, "vPositionScale" }, { ci::geom::Attrib::CUSTOM_2, "vTexCoordOffset" }, { ci::geom::Attrib::CUSTOM_3, "vTexCoordScale" }, { ci::geom::Attrib::CUSTOM_4, "iTex0" } });

```

Here is my vertex shader…

```
#version 150

uniform mat4 ciModelViewProjection;

in vec4 ciPosition;

in vec2 vPositionOffset;	
in vec2 vPositionScale;		
in vec2 vTexCoordOffset;	
in vec2 vTexCoordScale;	
in int iTex0;	

in vec2 ciTexCoord0;

out highp vec2 TexCoord;
flat out int iTexID;

void main( void )
{
	gl_Position = ciModelViewProjection * ( vec4( vPositionOffset, 0, 0 ) + vec4( vPositionScale, 1, 1 ) * ciPosition );
	TexCoord = vTexCoordOffset + vTexCoordScale * ciTexCoord0;
	iTexID = iTex0;
}

```

Fragment Shader

```
  #version 150

//uniform sampler2D uTex0;

uniform sampler2D uTempTex0[16];
in vec2	TexCoord;
flat in int iTexID;

out vec4 oColor;
		
void main( void ) 
{
	oColor = vec4( 1 ) * texture( uTempTex0[iTexID], TexCoord.st );
}
```

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [March 8, 2017, 9:59pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/5 "2017-03-08T21:59:50Z")

</div>

Hi,

I meant [these array textures](https://www.khronos.org/opengl/wiki/Array_Texture), not an array of `Texture2d`'s. While I don’t have code readily available, I believe array textures are supported in Cinder with the `Texture3d` class when you use the target `GL_TEXTURE_2D_ARRAY`. To specify the array index, use 3D texture coordinates; the z-component is used as the index.

-Paul

P.S.: there is a [test](https://github.com/cinder/Cinder/blob/master/test/_opengl/Texture3d/src/Texture3dApp.cpp) for this in the Cinder repo, might be of interest.

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 9, 2017, 8:26pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/6 "2017-03-09T20:26:25Z")

</div>

Unfortunately using an array textures means all the textures need to be the same size. I guess this is what you mean by preparing your data before hand.

I could have 3 (maybe more? ) texture atlases in my array texture and as long as i organised all my textures into those atlases i can optimise my GUI rendering?

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [March 9, 2017, 9:08pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/7 "2017-03-09T21:08:14Z")

</div>

Exactly, that is precisely what I meant. 🙂

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 9, 2017, 9:54pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/8 "2017-03-09T21:54:06Z")

</div>

ha ha, shader newbies need a while to catchup 🙂

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 10, 2017, 9:00pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/9 "2017-03-10T21:00:17Z")

</div>

I have moved on to primitives and meshes. Any samples, advice on how to batch a group of meshes? or a group of primitives(lines, points, line\_loops)? The meshes are different, not all the same. Same with primitives. I can draw one using ci::gl::draw() but it would be great if i can add them to a Vbo and then draw them using a shader.

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [March 11, 2017, 2:42am UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/10 "2017-03-11T02:42:21Z")

</div>

Have a look at `ci::gl::VertBatch` (see: `cinder/gl/Batch.h`). It allows you to easily construct a temporary mesh. It can contain any kind of primitive and you simply add vertices and attributes to it. Once constructed, you can render it just once, or many times if you so wish. I used it to render a bunch of debugging wireframe primitives in this image:

 ![](https://canada1.discourse-cdn.com/flex030/uploads/libcinder/original/1X/16451aef1a916a86cef1116e4115684fc5482a59.jpg)

(I wrote a class to easily draw cylinders, capsules, cones, boxes, wedges and spheres, called `Sketch` because it resembles `Batch`, but nobody seemed to like the name).

If you already have a vector of vertex data, it might be faster to actually construct a `VboMesh` instead, since this allows you to copy all data at once. If you make it big enough, you can even reuse it next frame. Make one for lines and one for triangles. Use `gl::draw( mMesh, first, count )` to specify how many vertices you want to draw this time.

-Paul

---

<div class="post-metadata">

**Author:** ![balachandran\_c](https://avatars.discourse-cdn.com/v4/letter/b/f17d59/32.png) [@balachandran\_c](https://discourse.libcinder.org/u/balachandran_c)\
**Post date:** [March 13, 2017, 12:35pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/11 "2017-03-13T12:35:37Z")

</div>

> [@paul.houx](#):
>
> It allows you to easily construct a temporary mesh.

Is it good only for temporary mesh? If so, why?

Thanks,  
Bala.

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [March 13, 2017, 9:26pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/12 "2017-03-13T21:26:19Z")

</div>

No, you can reuse the mesh as often as you want. I was hinting at using the mesh just once because the original question was about drawing a user interface, in which case you can assume the mesh does not stay the same from frame to frame.

-Paul

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 13, 2017, 9:59pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/13 "2017-03-13T21:59:39Z")

</div>

Thats great, i will look into VertBatches. Those screenshots give me a good idea of what i could achieve.

How would you recommend handling texture animations? I have added the frames of my animation to the array texture but i need to update the texcoords every time the animation updates to a new frame.

I am looking at something like this to solve this issue that i found in the samples. I dont think uniforms will work as they are applied to everything in the batch. I just want to index in to a particular texcoords and update just that one.

```
   auto mappedTexPosAttrib = m_MeshRef->mapAttrib2f(ci::geom::Attrib::CUSTOM_2, false);
			
	for (int i = 0; i < m_MeshRef->getNumVertices(); i++) {
         // keep iterating through the vertices till you find the vertices for the animation that changed
         // my mesh is a rect so i guess i divide by 4 to index into a particular textures rect? 
	     mappedTexPosAttrib.x = set new textcoord here;
	     mappedTexPosAttrib.y = set new textcoord here;
	    ++mappedTexPosAttrib;
	}

	mappedTexPosAttrib.unmap();
```

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [March 13, 2017, 10:10pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/14 "2017-03-13T22:10:45Z")

</div>

Hi,

yeah, that might work. A faster way of doing things is to keep an index into the buffer handy, so that you don’t have to iterate.

-Paul

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 13, 2017, 10:27pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/15 "2017-03-13T22:27:54Z")

</div>

Oh wow, i actually got it right 🙂 Am i right regarding my mesh is a rect so i divide by 4 to index into a particular textures rect?

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [March 13, 2017, 11:11pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/16 "2017-03-13T23:11:42Z")

</div>

Yes, if you use 4 vertices per rectangle, use GL\_TRIANGLES and have an index buffer with 6 indices per rectangle. 🙂

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 14, 2017, 10:57pm UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/17 "2017-03-14T22:57:54Z")

</div>

Right got it 🙂

Any reason why my textures dont seem to have alpha? They are png and i have transparent areas but all transparent areas appear black with my new render code. Below is my fragment shader. Only difference between mine and cinders stock shader is “[TexCoord.st](http://TexCoord.st)” is used.

```
uniform sampler2DArray uTex0;

in vec3	TexCoord;

out vec4 oColor;
		
void main( void ) 
{
	oColor = vec4( 1 ) * texture( uTex0, TexCoord.xyz );
}
```

---

<div class="post-metadata">

**Author:** ![paul.houx](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/paul.houx/32/31_2.png) [@paul.houx](https://discourse.libcinder.org/u/paul.houx)\
**Post date:** [March 15, 2017, 12:57am UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/18 "2017-03-15T00:57:42Z")

</div>

Did you forget to enable alpha blending perhaps?

---

<div class="post-metadata">

**Author:** ![SuperRockG](https://avatars.discourse-cdn.com/v4/letter/s/fbc32d/32.png) [@SuperRockG](https://discourse.libcinder.org/u/SuperRockG)\
**Post date:** [March 15, 2017, 11:04am UTC](https://discourse.libcinder.org/t/write-a-simple-renderer/594/19 "2017-03-15T11:04:13Z")

</div>

No,this is my drawing code…

```
ci::gl::enableAlphaBlending();
m_Tex2dArray->bind();		
m_BatchRef->drawInstanced(m_aInfo.size());
ci::gl::disableAlphaBlending();

```

I noticed that Texture3D default internal format is GL\_RGB.  
So i set the internal format to GL\_RGBA like below and that worked!

`ci::gl::Texture3d::create( 256, 256, 3, ci::gl::Texture3d::Format().target( GL_TEXTURE_2D_ARRAY ).internalFormat(GL_RGBA) );`
