Monday, August 26, 2013

CC3Material - part 1

As promised, this week I'll showcase the use of materials within the port Cocos3D-XNA. As a point of comparison, let's start off by creating four cubes that have no material associated with them, but instead are simply rendered with a single colour as seen below.


Click to enlarge


I've omitted the details on how to create and load the vertex data, which I'll leave for another post. For now, we're just interested in making our cubes look sexier! To do this, I created four different CC3Material objects, as so


CC3Material material = new CC3Material(0, "Glowy");
material.ShaderProgram = materialShaderProgram;
material.AmbientColor = new CCColor4F(0.0f, 0.1f, 0.1f, 1.0f);
material.DiffuseColor = new CCColor4F(0.5f, 0.5f, 1.0f, 1.0f);
material.SpecularColor = new CCColor4F(1.0f, 1.0f, 0.0f, 1.0f);
material.EmissionColor = new CCColor4F(0.5f, 0.5f, 0.0f, 1.0f);
material.Shininess = 100.0f;
material.ShouldUseLighting = true;

material = new CC3Material(1, "Grass");
material.ShaderProgram = materialShaderProgram;
material.AmbientColor = new CCColor4F(0.0f, 0.1f, 0.0f, 1.0f);
material.DiffuseColor = new CCColor4F(0.0f, 0.2f, 0.0f, 0.2f);
material.SpecularColor = new CCColor4F(0.0f, 1.0f, 0.0f, 1.0f);
material.EmissionColor = new CCColor4F(0.0f, 0.1f, 0.0f, 1.0f);
material.Shininess = 1.0f;
material.ShouldUseLighting = true;

material = new CC3Material(2, "Metal");
material.ShaderProgram = materialShaderProgram;
material.AmbientColor = new CCColor4F(0.0f, 0.3f, 0.9f, 1.0f);
material.DiffuseColor = new CCColor4F(0.0f, 0.0f, 1.0f, 1.0f);
material.SpecularColor = new CCColor4F(0.1f, 0.8f, 0.5f, 1.0f);
material.EmissionColor = new CCColor4F(0.0f, 0.2f, 1.0f, 1.0f);
material.Shininess = 100.0f;
material.ShouldUseLighting = true;  

material = new CC3Material(3, "Watery");
material.ShaderProgram = materialShaderProgram;
material.AmbientColor = new CCColor4F(0.1f, 0.9f, 0.0f, 1.0f);
material.DiffuseColor = new CCColor4F(0.9f, 0.5f, 0.9f, 0.5f);
material.SpecularColor = new CCColor4F(0.0f, 0.0f, 0.9f, 1.0f);
material.EmissionColor = new CCColor4F(0.1f, 0.15f, 0.15f, 1.0f);
material.Shininess = 1.0f;
material.ShouldUseLighting = true;

each of which have different attributes tweaked. You can check out this tutorial for a nice explanation on the effect of the different lighting/material contributions (ambient, specular, diffuse etc.). Personally, I'm no expert, so I found experimentation works best.

Finally, using an inbuilt Cocos3D-XNA shader (see last week), we can bind each of our four cubes with one of the materials, and behind the scenes Cocos3D will load these material ivars into corresponding shader uniforms.  In the end, our scene now looks like

Click to enlarge


which (I think) is much nicer than our original scene! Again some details have been glossed over, but hopefully you'll agree that creating a material in Cocos3D-XNA is fairly straight forward task.

Next week, I'll talk about incorporating textures into our materials to create even slicker effects.

Sunday, August 18, 2013

Using CC3ShaderProgramMatchers

Last week, I was talking about how to load a custom shader in Cocos3D-XNA. Well, what's nice about cocos3d is that it comes pre-bundled with a set of shaders that provide support for basic colouring, multi-texturing and bump map effects. Getting access to these shaders is handled by the CC3ShaderProgramMatchers class. For example to load the corresponding single texture shader we write

CC3ShaderProgram program = new CC3ShaderProgramMatchers().SingleTextureProgram();  

Once we have the shader, we would like to configure its parameters. However, in this instance a user shouldn't have to be burdened with understanding the innards of a shader they didn't write themselves. Thankfully, cocos3d does the heavy lifting of associating all bundled shaders' attributes/uniforms to corresponding instance variables belonging to a host of different objects.  As an example, within our bundled shaders we have the (sample of ) material uniforms

uniform float4 u_cc3MaterialAmbientColor;
uniform float4 u_cc3MaterialDiffuseColor;
uniform float4 u_cc3MaterialSpecularColor;
uniform float4 u_cc3MaterialEmissionColor;   

which are bound to the ivars

material.AmbientColor;
material.DiffuseColor;
material.SpecularColor;
material.EmissionColor;   

of the currently set CC3Material object within the graphics context. Other classes of interest include: CC3Light, CC3MeshNode, CC3PointParticleEmitter (along with others), which are similarly tied to a number of different shader parameters. So now to use these pre-bundled shaders, a user simply has to worry about setting a collection of ivars and cocos3d will make sure the correct shader parameters are updated.

Next week, I'll be putting all this theory into practice with the port Cocos3D-XNA by showing the basics of creating and using a material object!


Sunday, August 11, 2013

Setting shader values

Both cocos3D and XNA support the use of shaders. In the former case, these shader programs are written in GLSL, while XNA makes use of Microsoft's HLSL. As MonoGame (which Cocos3D-XNA  relies on) is a cross-platform implementation of XNA, there is a need to be shader language-agnostic, which by and large MonoGame achieves.

With that in mind, I wanted to show how a user can interact with a shader in the port Cocos3D-XNA. Loading a shader file is done by:

CC3ShaderProgram shader = new CC3ShaderProgram(0, "MyShader", semanticDelegate, "shaderFilename");
// Params info: tag, name, knows shader var types, location of shader file     

Once we have the shader object, we can start playing around with its parameters. Below is a sample of using a shader, originally written in HLSL, to incorporate lighting effects into the scene



Such an effect was produced by setting values to around ten different shader uniforms (constants), which is achieved by:

CC3ShaderUniform shaderUniform = shader.UniformNamed("uniformName");
shaderUniform.SetValue(someValue); 
// someValue can be of type float, vector, texture etc  

You might think manually setting so many uniforms is a cumbersome task, and in general, it would be nice if a user could use a bunch of common effects like multi texturing without having to roll their own shader. Thankfully, cocos3d has you covered, and in the upcoming weeks I'll (hopefully) showcase how this done in Cocos3D-XNA.


Sunday, August 4, 2013

Introduction


Hello! My name is Rami and I'm a student programmer participating in the 2013 Google Summer of Code (GSoC) with mentor organization Mono.

My project, Cocos3D-XNA, involves porting the 3d graphics library cocos3d from Objective-C to C#. With the aid of MonoGame --- an open source and cross-platform implementation of Microsoft's XNA 4.0 graphics framework, the aim is to similarly make Cocos3D-XNA a cross-platform port.

I'm about at the half-way point of GSoC (sorry, bit late in setting up my blog), so I thought I'd showcase the progress made so far.

Camera support

Firstly, in contrast to XNA/MonoGame, cocos3d has an in-built CC3Camera suite of classes that are responsible for updating the view and projection matrices of a scene base on changes to a camera's position, target, zoom factor etc. Additionally, cocos3d also includes support for animating these camera parameters. Here's an example of the port Cocos3D-XNA putting a perspective camera through its paces.



Shader/Texture support

Porting cocos3d's logic for loading/binding shader programs and textures primarily involved translating a lot of OpenGL calls into their corresponding XNA equivalents. Here's an example of the port rendering a scene using a simple single texture shader.



You can find both the demo code and API on GitHub here. Any comments or suggestions would be great. Just keep in mind there's still a lot left to be done!