Cel Shading on iOS

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Post Reply
User avatar
Mike_BirkHoff
Gnoblar
Posts: 13
Joined: Fri Aug 29, 2014 2:16 pm
Location: Düsseldorf - Germany
x 9

Cel Shading on iOS

Post by Mike_BirkHoff »

Hello Everyone,
I was trying to get a Cel Shader running on iOS. However the Enhanced Cel Shader program (http://www.ogre3d.org/tikiwiki/tiki-ind ... CelShading) is not supported by my iPhone 4S and the one from the examples just makes my mesh black. I would be very grateful for tips on how to get a Cel Shader running on iOS.

My code currently looks like this but the color of my texture is not used. Instead the color of the cel_shading_diffuse.png is used for texture lookup.


cel_shader_vertex.glsles:

Code: Select all

#version 100
precision mediump int;
precision mediump float;

/* Cel shading vertex program for single-pass rendering
   In this program, we want to calculate the diffuse and specular
   ramp components, and the edge factor (for doing simple outlining)
   For the outlining to look good, we need a pretty well curved model.
*/
// Parameters
attribute vec4 vertex;
attribute vec3 normal;
attribute vec4 uv0;

uniform vec3 lightPosition; // object space
uniform vec3 eyePosition;   // object space
uniform vec4 shininess;
uniform mat4 worldViewProj;

varying float diffuseIn;
varying float specularIn;
varying float edge;
varying vec4 uvIn;


void main()
{
	// calculate output position
	gl_Position = worldViewProj * vertex;

	// calculate light vector
	vec3 N = normalize(normal);
	vec3 L = normalize(lightPosition - vertex.xyz);
	vec3 E = normalize(eyePosition - vertex.xyz);
	
	// Calculate diffuse component
	diffuseIn = max(dot(N, L) , 0.0);

	// Mask off specular if diffuse is 0
	if (diffuseIn == 0.0)
	{
	    specularIn = 0.0;
	}
	else
	{
		// Calculate specular component
		vec3 H = normalize(L + E);
		specularIn = pow(max(dot(N, H), 0.0), shininess.x);
	}

	// Edge detection, dot eye and normal vectors
	edge = max(dot(N, E), 0.0);
	uvIn = uv0;
}

cel_shader_fragment.glsles:

Code: Select all

#version 100
precision mediump int;
precision mediump float;

/* Cel shading fragment program for single-pass rendering */
uniform vec4 diffuse;
uniform vec4 specular;
uniform sampler2D diffuseRamp;
uniform sampler2D specularRamp;
uniform sampler2D edgeRamp;
uniform sampler2D texture;

varying float diffuseIn;
varying float specularIn;
varying float edge;
varying vec4 uvIn;

void main()
{
	// Step functions from textures
	vec4 diffuseStep = texture2D(diffuseRamp, vec2(diffuseIn));
	vec4 specularStep = texture2D(specularRamp, vec2(specularIn));
	vec4 edgeStep = texture2D(edgeRamp, vec2(edge));

	gl_FragColor = edgeStep.x * ((texture2D(texture, uvIn.xy) * diffuseStep.x) + 
					(specular * specularStep.x));
}


Material File:

(dana_hair_clothes.png is a 8*8 pixel texture where simple colors are stored)

Code: Select all

material Clothes
{
    receive_shadows on 

    technique
    {

		pass Clothes
        {


			vertex_program_ref cel_shaderVPGLSL
			{
				// map shininess from custom renderable param 1
				param_named_auto shininess custom 1
			}
			fragment_program_ref cel_shaderFPGLSL
			{
				//	shared_params_ref lighting
				// map diffuse from custom renderable param 2
				param_named_auto diffuse custom 2
				// map specular from custom renderable param 3
				param_named_auto specular custom 3
				
				param_named_auto texture custom 4
			}
			texture_unit
			{
				texture cel_shading_diffuse.png 1d
				tex_address_mode clamp
				filtering none
			}
			texture_unit
			{
				texture cel_shading_specular.png 1d
				tex_address_mode clamp
				filtering none
			}
			texture_unit
			{
				texture cel_shading_edge.png 1d
				tex_address_mode clamp
				filtering none
			}

            texture_unit 
            {
                texture dana_hair_clothes.png
                tex_address_mode wrap
                scale 1.0 1.0
                colour_op modulate
            }

		}
			
    } 
}

Greetings Mike
Attachments
game.jpg
User avatar
Mike_BirkHoff
Gnoblar
Posts: 13
Joined: Fri Aug 29, 2014 2:16 pm
Location: Düsseldorf - Germany
x 9

Re: Cel Shading on iOS

Post by Mike_BirkHoff »

Solved it.
Be sure to set the float precision from the Vertex Shader to precision highp float; or you will have massive z fighting on newer devices.

This code is currently in development with many leftovers and no correct lighting. I will upload a clean version when I'm done with the project, but I figured this might still be useful for someone in the meantime.

Material File:

Code: Select all



vertex_program cel_shaderVPGLSL2 glsles
{
	source CelShadingVp2.glsles
	profiles glsles

	default_params
	{
		param_named_auto lightPosition 	light_position_object_space 0
		param_named_auto lightDiffuse  	light_diffuse_colour 0
		param_named_auto sceneAmbient   ambient_light_colour
		param_named_auto eyePosition 	camera_position_object_space
		param_named_auto worldViewProj 	worldviewproj_matrix
		
		param_named_auto near         near_clip_distance
      	param_named_auto far         far_clip_distance
		
		param_named 	shininess 		float 10 
	}


}

fragment_program cel_shaderFPGLSL2 glsles
{
	source CelShadingFp2.glsles
		default_params
		      {
		         	param_named diffuseRamp 	int 0
					param_named specularRamp	int 1
					param_named edgeRamp		int 2
		         	param_named texturee 		int 3
		      }
	profiles glsles
}

abstract pass Cel_Shader
{

	
	vertex_program_ref cel_shaderVPGLSL2
	{
		// map shininess from custom renderable param 1
		param_named_auto shininess custom 1
	}
	fragment_program_ref cel_shaderFPGLSL2
	{
		//	shared_params_ref lighting
		// map diffuse from custom renderable param 2
		param_named_auto diffuse custom 2
		// map specular from custom renderable param 3
		param_named_auto specular custom 3
		
	}

		texture_unit diffRamp
		{
			texture cel_shading_diffuse.png 1d
			tex_address_mode clamp
			filtering none
		}
		texture_unit specRamp
		{
			texture cel_shading_specular.png 1d
			tex_address_mode clamp
			filtering none
		}
		texture_unit edge
		{
			texture cel_shading_edge.png 1d
			tex_address_mode clamp
			filtering none
		}
	
		texture_unit tex
        {
        }

}

FragmentShader:

Code: Select all

#version 100
precision mediump int;
precision mediump float;

/* Cel shading fragment program for single-pass rendering */

uniform vec4 diffuse;
uniform vec4 specular;

uniform sampler2D diffuseRamp;
uniform sampler2D specularRamp;
uniform sampler2D edgeRamp;
uniform sampler2D texturee;

varying float 	diffuseIn;
varying float 	specularIn;
varying float 	edge;
varying vec4 	uvIn;
varying vec3 	lightIn;

void main()
{
	// Step functions from textures

	// Step functions from textures
	vec4 diffuseStep 	= texture2D(diffuseRamp, vec2(diffuseIn));
	vec4 specularStep 	= texture2D(specularRamp, vec2(specularIn));
	vec4 edgeStep 		= texture2D(edgeRamp, vec2(edge));
	vec4 diffTex		= texture2D(texturee, uvIn.xy);
	
	gl_FragColor = 	edgeStep * 
					(
	 					( ( vec4(diffTex.x* lightIn.x, diffTex.y* lightIn.y,diffTex.z* lightIn.z,diffTex.w) ) * diffuseStep.x)  
						+ (specular * specularStep) 
					);
}

Vertex Shader:

Code: Select all

#version 100
precision mediump int;
precision highp float;

/* Cel shading vertex program for single-pass rendering
   In this program, we want to calculate the diffuse and specular
   ramp components, and the edge factor (for doing simple outlining)
   For the outlining to look good, we need a pretty well curved model.
*/

#define NUM_LIGHTS 3

// Parameters
attribute vec4 vertex;
attribute vec3 normal;
attribute vec4 uv0;

uniform vec3 	lightPosition; // object space
uniform vec3 	eyePosition;   // object space
uniform vec4 	shininess;
uniform mat4 	worldViewProj;
uniform vec4 	lightDiffuse, sceneAmbient;

uniform float	near, far;

varying float 	diffuseIn;
varying float 	specularIn;
varying float 	edge;
varying vec4 	uvIn;
varying vec3 	lightIn;


void main()
{
	// calculate output position
	gl_Position = worldViewProj * vertex;

	//gl_Position.z = 2.0*log(gl_Position.w/near)/log(far/near) - 1.0; 
	//gl_Position.z *= gl_Position.w;

	vec3 N = normalize(normal);
	vec3 L;
	vec3 E = normalize(eyePosition - vertex.xyz);


	// calculate light vector

	L = normalize(lightPosition);


	// Calculate diffuse component
	diffuseIn = max(dot(L, N) , 0.0);

	// Mask off specular if diffuse is 0
	if (diffuseIn == 0.0)
	{
	    specularIn = 0.0;
	}
	else
	{
		// Calculate specular component
		vec3 H = normalize(L + E);
		specularIn = pow(max(dot(N, H), 0.0), shininess.x);
	}

	// Edge detection, dot eye and normal vectors
	edge = max(dot(N, E), 0.0);
	uvIn.xy = uv0.xy;
	lightIn = lightDiffuse.xyz + sceneAmbient.xyz;
}

Post Reply