1. outline

  OpenGLES 2.0 don't support glLightf. So developer have to make light effect using glsl shader. Following content don't explane  about OpenGL2.0 functions like glGetUniformLocation, glGetAttribLocation, ect. 

2. Light formula

  Below formual show graphics expression of light in 3D graphics.

I = Global Ambient  + Emission + Ambient + Diffuse + Specular

= Ga + Me + 1/a+bD+cD^2(Ka*Ia + Kd*Id(NㆍL) + Ks*Is(RㆍV)^n)

Ga = Global Ambient

Me = Material Emission

D = light distance from vertex

a = constant attenuation

b = linear attenuation

c = quadratic attenuation

Ka  = Material Ambient

Ia = Light Ambient

Kd = Material Diffuse

Id = Light Diffuse

Ks = Material Specular

Is  = Light Specular

N = Normal Unit Vector of Vertex

L = Light Unit Vector (i.e. Light Position - Vertex Position)

R = Reflection Unit Vector

V = View point Unit Vector

Global Ambient, Ambient, Diffuse, Spcrular, Emission, Attenuations and Position values are set by opengles 2.0 functions like glUniform4f, glUniform1f. 


I initialize material values 

//init material
m_material.ambient	= glGetUniformLocation(program, "material.ambient");
m_material.diffuse 	= glGetUniformLocation(program, "material.diffuse");
m_material.specular 	= glGetUniformLocation(program, "material.specular");
m_material.emission 	= glGetUniformLocation(program, "material.emission");
m_material.shininess 	= glGetUniformLocation(program, "material.shininess");

glUniform4f(m_material.ambient, 0.2f, 0.2f, 0.2f, 1.0f);
glUniform4f(m_material.diffuse, 0.8f, 0.8f, 0.8f, 1.0f);
glUniform4f(m_material.specular, 0.0f, 0.0f, 0.0f, 1.0f);
glUniform4f(m_material.emission, 0.0f, 0.0f, 0.0f, 1.0f);
glUniform1f(m_material.shininess, 0.0f);

Otherwise, Normal Vector, Reflection Vector, Eye Vector and Light Vector are set in shader.

Light Vector : Light Position - Vertex Position. Blow show shader code.

gl_Position = modelview * position; vec3 L = vec3(light_position.x - gl_Position.x, light_position.y - gl_Position.y, light_position.z - gl_Position.z); D = sqrt(L.x*L.x + L.y*L.y + L.z*L.z);

'D' is distance light and vertex. This is used to apply attenuation effect.

Normal Vector : This value is influenced by modelview matrix. If you translate your model, normal vector is also translated. So I made a Nomal-Matirx that is made by ModelView-Matrix.

m_Uniforms.NormalMatrix = glGetUniformLocation(m_current_shader_program,"normal_matrix");
glUniformMatrix3fv(m_Uniforms.NormalMatrix, 1, 0, m_model_view_matrix_stack.top()->ToMat3().Inverse().Transposed().Pointer());

To get Normal Matrix, I got 3x3 Matrix from Modelview Matrix. And I inversed and transpose this matrix. Lastly Send to shader matrix.

In shader, you can get normal vector. Below show shader code.

vec3 normalized_N 	= normalize(normal_matrix * normal);	//normal vector

Reflection Vector : This Vector is reflection of light-vector. You can get from Light vector and Normal Vector. Below show shader code.

vec3 normalized_R 	= normalize(dot(L, normalized_N)*2.0*normalized_N - L);		//reflection vector

Eye Vector :This Vector is direction of eye. Default is vec3(0,0,1). Also I use Default.

vec3 normalized_V 	= normalize(vec3(0.0, 0.0, 1.0));		//eye vector

Attenuation : Light is changed by distance. If light and vertex distance is close, light intensity is big. In 3D graphics, attenuation is expressed 

1/(a+ b*dD + c*D^2). 

attenuation = 1.0/(light[0].constant_attenuation + light[0].linear_attenuation*D + light[0].quadratic_attenuation*D*D);

3. Ambient + Diffuse + Specualr

Ambient is neighboring light. In 3d graphics, This value is expressed Ka*Ia/D^2. [Ka] is Material Ambient value. [Ia] is Light Ambient. D is distance. 

Diffuse is spread of light. This is Kd*Id*(NㆍL).

Specular is Ks*Is*((RㆍV)^n)

Below show shader code.

float df = max(0.0, dot(normalized_N, normalized_L));							//get diffuse constant
float sf = max(0.0, dot(normalized_R, normalized_V));							//get specualr constant
float shininess = clamp(material.shininess, 0.0, 128.0);
if(material.shininess != 0.0)
	sf = pow(sf, material.shininess);

float attenuation = 1.0;
float spot_exponent_value = 1.0;
if(light[0].position.w != 0.0)
	attenuation = 1.0/(light[0].constant_attenuation + light[0].linear_attenuation*D + light[0].quadratic_attenuation*D*D);
	spot_exponent_value = pow(max(0.0,spotlight_dot),light[0].spot_exponent);
//get color
vec4 ambient_value = light[0].ambient*material.ambient*attenuation;
vec4 diffuse_value = df*light[0].diffuse*material.diffuse*attenuation*spot_exponent_value;
vec4 specualr_value = sf*light[0].specular*material.specular*attenuation*spot_exponent_value;   
sum_color = global_ambient + material.emission + ambient_value + diffuse_value;

df is inner product Normal Vector and Light Vector. This is used in diffuse. sf is ((RㆍV)^n) that used in Specular.

4. Result Scene

This is OpenGL test App (OpenGL Diary)

'NDK & OpenGL ES' 카테고리의 다른 글

Android, NDK OpenGLES2.0 Texture  (0) 2014.09.22
OpenGLES2.0 GLSL, 2D Basic shader  (1) 2014.09.18
OpenGLES 2.0,GLSL lighting code  (0) 2014.09.15
GLSL, OpenGLES2.0 glFog  (0) 2014.09.12
NDK AdMob, Can't see admob on Framelayout  (0) 2014.09.10
GLSurfaceView & GLRenderer 설정  (0) 2014.04.15