Implement materials and lights.

Bug 22124687

Change-Id: Ic8a458962e370f372c2e97052c9c86f9b5c6dede
Reviewed-on: https://swiftshader-review.googlesource.com/3511
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLES_CM/Context.cpp b/src/OpenGL/libGLES_CM/Context.cpp
index 0217cce..7096c32 100644
--- a/src/OpenGL/libGLES_CM/Context.cpp
+++ b/src/OpenGL/libGLES_CM/Context.cpp
@@ -30,6 +30,8 @@
 

 #include <EGL/eglext.h>

 

+#include <algorithm>

+

 #undef near

 #undef far

 

@@ -180,6 +182,7 @@
 	materialDiffuse = {0.8f, 0.8f, 0.8f, 1.0f};

 	materialSpecular = {0.0f, 0.0f, 0.0f, 1.0f};

 	materialEmission = {0.0f, 0.0f, 0.0f, 1.0f};

+	materialShininess = 0.0f;

 

 	matrixMode = GL_MODELVIEW;

     

@@ -601,6 +604,51 @@
 	light[index].attenuation.quadratic = quadratic;

 }

 

+void Context::setGlobalAmbient(float red, float green, float blue, float alpha)

+{

+	globalAmbient.red = red;

+	globalAmbient.green = green;

+	globalAmbient.blue = blue;

+	globalAmbient.alpha = alpha;

+}

+

+void Context::setMaterialAmbient(float red, float green, float blue, float alpha)

+{

+	materialAmbient.red = red;

+	materialAmbient.green = green;

+	materialAmbient.blue = blue;

+	materialAmbient.alpha = alpha;

+}

+

+void Context::setMaterialDiffuse(float red, float green, float blue, float alpha)

+{

+	materialDiffuse.red = red;

+	materialDiffuse.green = green;

+	materialDiffuse.blue = blue;

+	materialDiffuse.alpha = alpha;

+}

+

+void Context::setMaterialSpecular(float red, float green, float blue, float alpha)

+{

+	materialSpecular.red = red;

+	materialSpecular.green = green;

+	materialSpecular.blue = blue;

+	materialSpecular.alpha = alpha;

+}

+

+void Context::setMaterialEmission(float red, float green, float blue, float alpha)

+{

+	materialEmission.red = red;

+	materialEmission.green = green;

+	materialEmission.blue = blue;

+	materialEmission.alpha = alpha;

+}

+

+void Context::setMaterialShininess(float shininess)

+{

+	materialShininess = shininess;

+}

+

 void Context::setFog(bool enable)

 {

 	device->setFogEnable(enable);

@@ -1732,9 +1780,11 @@
 		{

 			device->setLightPosition(i, sw::Point(light[i].position.x / light[i].position.w, light[i].position.y / light[i].position.w, light[i].position.z / light[i].position.w));

 		}

-		else   // Hack: set the position far way

+		else   // Directional light

 		{

-			device->setLightPosition(i, sw::Point(1e10f * light[i].position.x, 1e10f * light[i].position.y, 1e10f * light[i].position.z));

+			// Hack: set the position far way

+			float max = std::max(std::max(abs(light[i].position.x), abs(light[i].position.y)), abs(light[i].position.z));

+			device->setLightPosition(i, sw::Point(1e10f * (light[i].position.x / max), 1e10f * (light[i].position.y / max), 1e10f * (light[i].position.z / max)));

 		}

 	}

 

@@ -1742,6 +1792,7 @@
 	device->setMaterialDiffuse(sw::Color<float>(materialDiffuse.red, materialDiffuse.green, materialDiffuse.blue, materialDiffuse.alpha));

 	device->setMaterialSpecular(sw::Color<float>(materialSpecular.red, materialSpecular.green, materialSpecular.blue, materialSpecular.alpha));

 	device->setMaterialEmission(sw::Color<float>(materialEmission.red, materialEmission.green, materialEmission.blue, materialEmission.alpha));

+	device->setMaterialShininess(materialShininess);

 

     device->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL);

 	device->setSpecularMaterialSource(sw::MATERIAL_MATERIAL);

diff --git a/src/OpenGL/libGLES_CM/Context.h b/src/OpenGL/libGLES_CM/Context.h
index 644e6e8..71831e7 100644
--- a/src/OpenGL/libGLES_CM/Context.h
+++ b/src/OpenGL/libGLES_CM/Context.h
@@ -334,6 +334,13 @@
 	void setLightAttenuationConstant(int index, float constant);

 	void setLightAttenuationLinear(int index, float linear);

 	void setLightAttenuationQuadratic(int index, float quadratic);

+	

+	void setGlobalAmbient(float red, float green, float blue, float alpha);

+	void setMaterialAmbient(float red, float green, float blue, float alpha);

+	void setMaterialDiffuse(float red, float green, float blue, float alpha);

+	void setMaterialSpecular(float red, float green, float blue, float alpha);

+	void setMaterialEmission(float red, float green, float blue, float alpha);

+	void setMaterialShininess(float shininess);

 

 	void setFog(bool enabled);

 	void setFogMode(GLenum mode);

@@ -508,6 +515,7 @@
 	Color materialDiffuse;

 	Color materialSpecular;

 	Color materialEmission;

+	GLfloat materialShininess;

 

     // Recorded errors

     bool mInvalidEnum;

diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.cpp b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
index b5fcdd6..749fced 100644
--- a/src/OpenGL/libGLES_CM/libGLES_CM.cpp
+++ b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
@@ -2432,7 +2432,24 @@
 

 void LightModelfv(GLenum pname, const GLfloat *params)

 {

-	UNIMPLEMENTED();

+	TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname);

+

+	es1::Context *context = es1::getContext();

+

+	if(context)

+	{

+		switch(pname)

+		{

+		case GL_LIGHT_MODEL_AMBIENT:

+			context->setGlobalAmbient(params[0], params[1], params[2], params[3]);

+			break;

+		case GL_LIGHT_MODEL_TWO_SIDE:

+			UNIMPLEMENTED();

+			break;

+		default:

+			return error(GL_INVALID_ENUM);

+		}

+	}

 }

 

 void LightModelx(GLenum pname, GLfixed param)

@@ -2447,7 +2464,30 @@
 

 void Lightf(GLenum light, GLenum pname, GLfloat param)

 {

-	UNIMPLEMENTED();

+	TRACE("(GLenum light = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", light, pname, param);

+

+	int index = light - GL_LIGHT0;

+

+	if(index < 0 || index >= es1::MAX_LIGHTS)

+	{

+		return error(GL_INVALID_ENUM);

+	}

+

+	es1::Context *context = es1::getContext();

+

+	if(context)

+	{

+		switch(pname)

+		{

+		case GL_SPOT_EXPONENT:         UNIMPLEMENTED(); break;

+		case GL_SPOT_CUTOFF:           UNIMPLEMENTED(); break;

+		case GL_CONSTANT_ATTENUATION:  context->setLightAttenuationConstant(index, param);                       break;

+		case GL_LINEAR_ATTENUATION:    context->setLightAttenuationLinear(index, param);                         break;

+		case GL_QUADRATIC_ATTENUATION: context->setLightAttenuationQuadratic(index, param);                      break;

+		default:

+			return error(GL_INVALID_ENUM);

+		}

+	}

 }

 

 void Lightfv(GLenum light, GLenum pname, const GLfloat *params)

@@ -2551,12 +2591,66 @@
 

 void Materialf(GLenum face, GLenum pname, GLfloat param)

 {

-	UNIMPLEMENTED();

+	TRACE("(GLenum face = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", face, pname, param);

+

+	if(face != GL_FRONT_AND_BACK)

+	{

+		return error(GL_INVALID_ENUM);

+	}

+

+	es1::Context *context = es1::getContext();

+

+	if(context)

+	{

+		switch(pname)

+		{

+		case GL_SHININESS:

+			context->setMaterialShininess(param);

+			break;

+		default:

+			return error(GL_INVALID_ENUM);

+		}

+	}

 }

 

 void Materialfv(GLenum face, GLenum pname, const GLfloat *params)

 {

-	UNIMPLEMENTED();

+	TRACE("(GLenum face = 0x%X, GLenum pname = 0x%X, GLfloat params)", face, pname);

+

+	if(face != GL_FRONT_AND_BACK)

+	{

+		return error(GL_INVALID_ENUM);

+	}

+

+	es1::Context *context = es1::getContext();

+

+	if(context)

+	{

+		switch(pname)

+		{

+		case GL_AMBIENT:

+			context->setMaterialAmbient(params[0], params[1], params[2], params[3]);

+			break;

+		case GL_DIFFUSE:

+			context->setMaterialDiffuse(params[0], params[1], params[2], params[3]);

+			break;

+		case GL_AMBIENT_AND_DIFFUSE:

+			context->setMaterialAmbient(params[0], params[1], params[2], params[3]);

+			context->setMaterialDiffuse(params[0], params[1], params[2], params[3]);

+			break;

+		case GL_SPECULAR:

+			context->setMaterialSpecular(params[0], params[1], params[2], params[3]);

+			break;

+		case GL_EMISSION:

+			context->setMaterialEmission(params[0], params[1], params[2], params[3]);

+			break;

+		case GL_SHININESS:

+			context->setMaterialShininess(params[0]);

+			break;

+		default:

+			return error(GL_INVALID_ENUM);

+		}

+	}

 }

 

 void Materialx(GLenum face, GLenum pname, GLfixed param)