[solved] Simple vertex-lighting shader

Get answers to all your basic programming questions. No Ogre questions, please!
Post Reply
technique
Halfling
Posts: 91
Joined: Fri Oct 22, 2010 10:46 pm
x 8

[solved] Simple vertex-lighting shader

Post by technique »

Hi,

i need my own simple vertex lighting shader to get rid of the alpha-rejection problem for mobile devices (opengl es 2.0) as described here (http://www.ogre3d.org/forums/viewtopic.php?f=1&t=79617). Back in times i wrote a few shaders for my own opengl frameworks and for a small open es 2.0 app aswell but i never did for my ogre games.

I will post my whole progress - and the solutions - so i hope it will be helpful for somebody.

I stuck with the very very first simple solid shading - so might be easy to help me out for this first step.

So following script just transform the vertices and paint the resulting fragments white. Just working while im using "gl_Position = ftransform();" but it just fails (mesh is completly gone) for "gl_Position = mWorldViewProjMat * vertex;" which probably should do the same as ftransform().

I want to use glsles so i can't use ftransform() and according to http://www.ogre3d.org/docs/manual/manua ... -in-a-Pass "mWorldViewProjMat" is exact what i need and the vertex buffer data according to http://www.ogre3d.org/docs/manual/manual_21.html can just be accessed with "attribute vec4 vertex;".

Whats wrong with my very simple basic first start?

Material:

Code: Select all

fragment_program alpha_rejection_fp_glsl glsl
{
	source alpha_rejection_fp.glsl
	
	param_named_auto mTexture0 						int 0
}

vertex_program alpha_rejection_vp_glsl glsl
{
	source alpha_rejection_vp.glsl
	
	param_named_auto mWorldViewMat 		worldview_matrix   
	param_named_auto mWorldViewProjMat 	worldviewproj_matrix
}

fragment_program alpha_rejection_fp unified
{
    delegate alpha_rejection_fp_glsl
}

vertex_program alpha_rejection_vp unified
{
    delegate alpha_rejection_vp_glsl
}

material alpha_rejection
{
	technique
	{
		pass
		{
		
			vertex_program_ref alpha_rejection_vp
			{
			}
		
			fragment_program_ref alpha_rejection_fp
			{
			}			
		}
	}
}
VERTEX SHADER:

Code: Select all

uniform mat4 mWorldViewMat, mWorldViewProjMat;

attribute vec4 vertex;

void main()
{
   //gl_Position 	= mWorldViewProjMat * vertex;
   gl_Position =  ftransform();
}
FRAGMENT SHADER:

Code: Select all

void main(void)
{
	gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
Last edited by technique on Sun Dec 01, 2013 9:13 pm, edited 2 times in total.
Image
Kingdoms Defender offers Tower Defense action with breathtaking 3-D graphics for your mobile Android device.

Give it a try:
Free-Version:
http://play.google.com/store/apps/detai ... ender_free

Full-Version:
http://play.google.com/store/apps/detai ... msdefender
technique
Halfling
Posts: 91
Joined: Fri Oct 22, 2010 10:46 pm
x 8

Re: Simple vertex-lighting shader

Post by technique »

Okay - solid shading is working. The vertex data can't be used as it is. You need to make sure the .w component is set to 1.

"gl_Position = worldViewProjMatrix * vec4(vertex.xyz, 1.0);"

Next to come: vertex-lighting.
Image
Kingdoms Defender offers Tower Defense action with breathtaking 3-D graphics for your mobile Android device.

Give it a try:
Free-Version:
http://play.google.com/store/apps/detai ... ender_free

Full-Version:
http://play.google.com/store/apps/detai ... msdefender
technique
Halfling
Posts: 91
Joined: Fri Oct 22, 2010 10:46 pm
x 8

Re: Simple vertex-lighting shader

Post by technique »

Okay i'm mostly done - but the specular term isnt computed correctly compared to the standard RTSS-Shader. The following code rendered just the specular light term and only for one directional light.

Whats wrong with my specular computation?

Material

Code: Select all

fragment_program alpha_rejection_fp_glsl glsl
{
	source alpha_rejection_fp.glsl
	param_named_auto textureSampler int 0
}

vertex_program alpha_rejection_vp_glsl glsl
{
	source alpha_rejection_vp.glsl
	
	default_params
	{
		param_named_auto worldViewProjMatrix 	worldviewproj_matrix
		param_named_auto normalMatrix			inverse_transpose_worldview_matrix
		param_named_auto worldViewMatrix		worldview_matrix
		param_named_auto lightPosition			light_position 0
		param_named_auto lightDirection			light_direction 0
		param_named_auto lightDiffuse			light_diffuse_colour 0
		param_named_auto lightSpecular			light_specular_colour 0
		param_named_auto eyePosition			camera_position
		param_named_auto sceneAmbient			ambient_light_colour
        param_named_auto surfaceDiffuse 		surface_diffuse_colour
		param_named_auto surfaceAmbient 		surface_ambient_colour
		param_named_auto surfaceSpecular		surface_specular_colour
		param_named_auto surfaceShininess		surface_shininess
	}
}

fragment_program alpha_rejection_fp unified
{
    delegate alpha_rejection_fp_glsl
}

vertex_program alpha_rejection_vp unified
{
    delegate alpha_rejection_vp_glsl
}

material alpha_rejection
{
	technique
	{
		pass
		{
		
			vertex_program_ref alpha_rejection_vp
			{
			}
		
			fragment_program_ref alpha_rejection_fp
			{
			}			
		}
	}
}
Vertex-Shader

Code: Select all

uniform mat4 worldViewProjMatrix;
uniform mat3 normalMatrix;
uniform mat4 worldViewMatrix;

uniform vec4 lightPosition, lightDirection, lightSpecular, lightDiffuse, sceneAmbient;
uniform vec4 surfaceAmbient, surfaceDiffuse, surfaceSpecular, surfaceShininess;
uniform vec3 eyePosition;

attribute vec4 vertex;
attribute vec3 normal;
attribute vec2 uv0;

varying vec4 vp_color;
varying vec2 vp_uv;

void main()
{
	// vertex normal in world space
	vec3 _normal = normalize(normalMatrix * normal);
	
	// vertex position in world space
	vec4 _vertex = worldViewMatrix * vec4(vertex.xyz, 1.0);
	
	// directional light direction
	vec3 _lightDirection = normalize(lightPosition.xyz);
	
	// angle between normal and light direction
	float _NdotL = max(dot(_normal, _lightDirection), 0.0);
	
	// compute diffuse term
	vec4 _diffuse = _NdotL * surfaceDiffuse * lightDiffuse;	
	
	// compute specular term
	vec3 _vertexToEye = eyePosition - _vertex.xyz;
	vec3 _reflection = reflect(-_lightDirection, _normal);
	vec4 _specular = surfaceSpecular * lightSpecular * pow(max(0.0, dot(_reflection, _vertexToEye)), length(surfaceShininess));
		
	// compute ambient term
	vec4 _ambient = surfaceAmbient * sceneAmbient;
	
	// resulting color (e.g. the light) will be interpolated over the triangle
	vp_color 	= vec4(_specular.xyz, 1.0); // + _specular + */ _ambient;
	vp_uv		= uv0;
	
	gl_Position = worldViewProjMatrix * vec4(vertex.xyz, 1.0);
}

Fragment-Shader:

Code: Select all

uniform sampler2D textureSampler;

varying vec4 vp_color;
varying vec2 vp_uv;

void main(void)
{
	vec4 _color = texture2D(textureSampler, vp_uv);
	
	_color.w = 1.0;
	gl_FragColor = vp_color;
}
Image
Kingdoms Defender offers Tower Defense action with breathtaking 3-D graphics for your mobile Android device.

Give it a try:
Free-Version:
http://play.google.com/store/apps/detai ... ender_free

Full-Version:
http://play.google.com/store/apps/detai ... msdefender
technique
Halfling
Posts: 91
Joined: Fri Oct 22, 2010 10:46 pm
x 8

Re: Simple vertex-lighting shader

Post by technique »

Okay - there is no need for transforming the incoming normals with the inverse transposed world-view matrix. This was the problem.

The "surface_alpha_rejection_value" parameter for the defined alpha_rejection value from the material pass did not work. This is a bad thing because this was the reason i wrote the shader.

According to https://ogre3d.atlassian.net/browse/OGRE-166 the parameter should exist - did anyone know how to use it or what i should do instead of using it?

Material

Code: Select all

fragment_program alpha_rejection_fp_glsl glsl
{
	source alpha_rejection_fp.glsl
	param_named_auto textureSampler int 0
}

vertex_program alpha_rejection_vp_glsl glsl
{
	source alpha_rejection_vp.glsl
	
	default_params
	{
		param_named_auto worldViewProjMatrix 	worldviewproj_matrix
		param_named_auto normalMatrix			inverse_transpose_worldview_matrix
		param_named_auto worldViewMatrix		worldview_matrix
		param_named_auto lightPosition			light_position 0
		param_named_auto lightDirection			light_direction 0
		param_named_auto lightDiffuse			light_diffuse_colour 0
		param_named_auto lightSpecular			light_specular_colour 0
		param_named_auto eyePosition			camera_position
		param_named_auto sceneAmbient			ambient_light_colour
        param_named_auto surfaceDiffuse 		surface_diffuse_colour
		param_named_auto surfaceAmbient 		surface_ambient_colour
		param_named_auto surfaceSpecular		surface_specular_colour
		param_named_auto surfaceShininess		surface_shininess
	}
}

fragment_program alpha_rejection_fp unified
{
    delegate alpha_rejection_fp_glsl
}

vertex_program alpha_rejection_vp unified
{
    delegate alpha_rejection_vp_glsl
}

material alpha_rejection
{
	technique
	{
		pass
		{
		
			vertex_program_ref alpha_rejection_vp
			{
			}
		
			fragment_program_ref alpha_rejection_fp
			{
			}			
		}
	}
}
Vertex-Shader

Code: Select all

uniform mat4 worldViewProjMatrix;
uniform mat3 normalMatrix;
uniform mat4 worldViewMatrix;

uniform vec4 lightPosition, lightDirection, lightSpecular, lightDiffuse, sceneAmbient;
uniform vec4 surfaceAmbient, surfaceDiffuse, surfaceSpecular, surfaceShininess;
uniform vec3 eyePosition;

attribute vec4 vertex;
attribute vec3 normal;
attribute vec2 uv0;

varying vec4 vp_color;
varying vec2 vp_uv;

void main()
{
	// vertex normal in world space
	vec3 _normal = normalize(normal);
	
	// vertex position in world space
	vec4 _vertex = worldViewMatrix * vec4(vertex.xyz, 1.0);
	
	// directional light direction
	vec3 _lightDirection = normalize(lightPosition.xyz);
	
	// angle between normal and light direction
	float _NdotL = max(dot(_normal, _lightDirection), 0.0);
	
	// compute diffuse term
	vec4 _diffuse = _NdotL * surfaceDiffuse * lightDiffuse;	
	
	// compute specular term
	vec3 _vertexToEye = eyePosition - _vertex.xyz;
	vec3 _reflection = reflect(-_lightDirection, _normal);
	vec4 _specular = surfaceSpecular * lightSpecular * pow(max(0.0, dot(_reflection, _vertexToEye)), length(surfaceShininess));
		
	// compute ambient term
	vec4 _ambient = surfaceAmbient * sceneAmbient;
	
	// resulting color (e.g. the light) will be interpolated over the triangle
	vp_color 	= vec4((_diffuse + _specular + _ambient).xyz, 1.0);
	vp_uv		= uv0;
	
	gl_Position = worldViewProjMatrix * vec4(vertex.xyz, 1.0);
}

Fragment-Shader:

Code: Select all

uniform sampler2D textureSampler;
uniform float alphaRejection;

varying vec4 vp_color;
varying vec2 vp_uv;

void main(void)
{
	vec4 _color = texture2D(textureSampler, vp_uv);
	if(_color.a < alphaRejection) discard;
	_color.a = 1.0;
	gl_FragColor = _color * vp_color;
}
Image
Kingdoms Defender offers Tower Defense action with breathtaking 3-D graphics for your mobile Android device.

Give it a try:
Free-Version:
http://play.google.com/store/apps/detai ... ender_free

Full-Version:
http://play.google.com/store/apps/detai ... msdefender
technique
Halfling
Posts: 91
Joined: Fri Oct 22, 2010 10:46 pm
x 8

Re: Simple vertex-lighting shader

Post by technique »

Added Specular shininess fix + blinn model and the GLSLES shader port. Since the alpha_rejection value isnt usable i m using a hardcoded value (128.0 / 255.0) and adjust a few of my textures to fit this value. For now its okay to work with a fixed threshhold.
After porting to glsles (just adding a few header lines) i could not get them to work.

I got an Ogre exception:
[...]
12-01 19:26:56.420: I/OGRE(24821): Parsing script alpha_rejection.program
12-01 19:26:56.445: E/OGRE(24821): Compiler error: invalid parameters in (6)
[...]
12-01 19:30:08.605: E/OGRE(25334): OGRE EXCEPTION(3:RenderingAPIException): Attempted to create a shader program without both a vertex and fragment program. in GLSLESProgramCommon::GLSLESProgramCommon at ..\..\..\RenderSystems\GLES2\src\GLSLES\src\OgreGLSLESProgramCommon.cpp (line 69)
12-01 19:30:08.610: E/OGRE(25334): OGRE EXCEPTION(3:RenderingAPIException): Attempted to create a shader program without both a vertex and fragment program. in GLSLESProgramCommon::GLSLESProgramCommon at ..\..\..\RenderSystems\GLES2\src\GLSLES\src\OgreGLSLESProgramCommon.cpp (line 69)
12-01 19:30:08.610: E/OGRE(25334): OGRE EXCEPTION(3:RenderingAPIException): Attempted to create a shader program without both a vertex and fragment program. in GLSLESProgramCommon::GLSLESProgramCommon at ..\..\..\RenderSystems\GLES2\src\GLSLES\src\OgreGLSLESProgramCommon.cpp (line 69)
12-01 19:30:08.615: A/libc(25334): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 25357 (e3d.gles2Sample)
Somthing wrong with this line?
...
param_named_auto textureSampler int 0
...


This is my whole shader setup:

alpha_rejection.program

Code: Select all

fragment_program alpha_rejection_fp_glsles glsles
{
	source alpha_rejection_fp.glsles
	default_params
    {
		param_named_auto textureSampler int 0
		//param_named_auto alphaRejection surface_alpha_rejection_value
	}
}

vertex_program alpha_rejection_vp_glsles glsles
{
	source alpha_rejection_vp.glsles
	
	default_params
	{
		param_named_auto worldViewProjMatrix 	worldviewproj_matrix
		param_named_auto normalMatrix			inverse_transpose_worldview_matrix
		param_named_auto worldViewMatrix		worldview_matrix
		param_named_auto lightPosition			light_position 0
		param_named_auto lightDirection			light_direction 0
		param_named_auto lightDiffuse			light_diffuse_colour 0
		param_named_auto lightSpecular			light_specular_colour 0
		param_named_auto eyePosition			camera_position
		param_named_auto sceneAmbient			ambient_light_colour
        param_named_auto surfaceDiffuse 		surface_diffuse_colour
		param_named_auto surfaceAmbient 		surface_ambient_colour
		param_named_auto surfaceSpecular		surface_specular_colour
		param_named_auto surfaceShininess		surface_shininess
	}
}

fragment_program alpha_rejection_fp unified
{
    delegate alpha_rejection_fp_glsles
}

vertex_program alpha_rejection_vp unified
{
    delegate alpha_rejection_vp_glsles
}
vertex-shader

Code: Select all

#version 100

precision mediump int;
precision mediump float;

uniform mat4 worldViewProjMatrix;
uniform mat3 normalMatrix;
uniform mat4 worldViewMatrix;

uniform vec4 lightPosition, lightDirection, lightSpecular, lightDiffuse, sceneAmbient;
uniform vec4 surfaceAmbient, surfaceDiffuse, surfaceSpecular;
uniform vec3 eyePosition;
uniform float surfaceShininess;

attribute vec4 vertex;
attribute vec3 normal;
attribute vec2 uv0;

varying vec4 vp_color;
varying vec2 vp_uv;

void main()
{
	// vertex normal in world space
	vec3 _normal = normalize(normal);
	
	// vertex position in world space
	vec4 _vertex = worldViewMatrix * vec4(vertex.xyz, 1.0);
	
	// directional light direction
	vec3 _lightDirection = normalize(lightPosition.xyz);
	
	// angle between normal and light direction
	float _NdotL = max(dot(_normal, _lightDirection), 0.0);
	
	// compute diffuse term
	vec4 _diffuse = _NdotL * surfaceDiffuse * lightDiffuse;	
	
	float shininess = max(1.0, surfaceShininess);
	
	// compute specular term
	/*
	vec3 _vertexToEye = eyePosition - _vertex.xyz;
	vec3 _reflection = reflect(-_lightDirection, _normal);
	vec4 _specular = vec4(0.0, 0.0, 0.0, 0.0);
	if(_NdotL > 0.0)
	{
		_specular = surfaceSpecular * lightSpecular * pow(max(0.0, dot(_reflection, _vertexToEye)), shininess);
	}
	*/
	
	
	vec3 _halfVector = normalize(_lightDirection + eyePosition);
	float _sf = max(0.0, dot(_normal, _halfVector));
	_sf = pow(_sf, shininess);
	vec4 _specular = surfaceSpecular * lightSpecular * _sf;
	
	// compute ambient term
	vec4 _ambient = surfaceAmbient * sceneAmbient;
	
	// resulting color (e.g. the light) will be interpolated over the triangle
	vp_color 	= vec4((_diffuse + _ambient + _specular).xyz, 1.0);
	vp_uv		= uv0;
	
	gl_Position = worldViewProjMatrix * vec4(vertex.xyz, 1.0);
}

fragment-shader

Code: Select all

#version 100

precision mediump int;
precision mediump float;

uniform sampler2D textureSampler;
//uniform float alphaRejection;

varying vec4 vp_color;
varying vec2 vp_uv;

void main()
{
	vec4 _color = texture2D(textureSampler, vp_uv);
	if(_color.a < (128.0 / 255.0)) discard;
	_color.a = 1.0;
	gl_FragColor = _color * vp_color;
}
material-script

Code: Select all

material alpha_rejection
{
	technique
	{
		pass
		{
		
			vertex_program_ref alpha_rejection_vp
			{
			}
		
			fragment_program_ref alpha_rejection_fp
			{
			}			
		}
	}
}

And a material skript which uses the shader:

Code: Select all

import * from "alpha_rejection.material"

material leaf : alpha_rejection
{
	technique
	{
		pass
		{
		
			diffuse 0.8 0.8 0.8 1.0
			ambient 0.8 0.8 0.8 1.0
			
			scene_blend alpha_blend
			alpha_rejection greater 254
			
			texture_unit
			{	       	
				texture leaf.png
			}
		}
	}
}

Image
Kingdoms Defender offers Tower Defense action with breathtaking 3-D graphics for your mobile Android device.

Give it a try:
Free-Version:
http://play.google.com/store/apps/detai ... ender_free

Full-Version:
http://play.google.com/store/apps/detai ... msdefender
technique
Halfling
Posts: 91
Joined: Fri Oct 22, 2010 10:46 pm
x 8

Re: Simple vertex-lighting shader

Post by technique »

Okay it was another shader problem using the bloom compositor - there is not relation to my shader the code above is just working fine!
Image
Kingdoms Defender offers Tower Defense action with breathtaking 3-D graphics for your mobile Android device.

Give it a try:
Free-Version:
http://play.google.com/store/apps/detai ... ender_free

Full-Version:
http://play.google.com/store/apps/detai ... msdefender
Post Reply