1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Light amount test.
22 *//*--------------------------------------------------------------------*/
23
24#include "es2fLightAmountTest.hpp"
25#include "tcuStringTemplate.hpp"
26#include "gluDefs.hpp"
27#include "gluShaderProgram.hpp"
28#include "tcuTestLog.hpp"
29#include "deStringUtil.hpp"
30#include "deInt32.h"
31#include "deRandom.h"
32
33#include <stdio.h>
34#include <vector>
35
36#include "glw.h"
37
38using namespace std;
39
40namespace deqp
41{
42namespace gles2
43{
44namespace Functional
45{
46
47const char* s_noLightsVertexShader =
48	"uniform mat4 u_modelviewMatrix;\n"
49	"uniform mat4 u_modelviewProjectionMatrix;\n"
50	"uniform mat3 u_normalMatrix;\n"
51	"\n"
52	"attribute vec4 a_position;\n"
53	"attribute vec3 a_normal;\n"
54	"\n"
55	"varying vec3 v_color;\n"
56	"\n"
57	"void main()\n"
58	"{\n"
59	"	v_color = vec3(0.0);\n"
60	"	gl_Position = u_modelviewProjectionMatrix * a_position;\n"
61	"}\n"
62;
63
64const char* s_vertexShaderTemplate =
65	"struct Light\n"
66	"{\n"
67	"	vec3	position;\n"
68	"	vec3	diffuse;\n"
69	"	vec3	specular;\n"
70	"	vec3	attenuation;\n"
71	"};\n"
72	"uniform Light u_lights[${NUM_DIR_LIGHTS} + ${NUM_OMNI_LIGHTS}];\n"
73	"uniform mat4 u_modelviewMatrix;\n"
74	"uniform mat4 u_modelviewProjectionMatrix;\n"
75	"uniform mat3 u_normalMatrix;\n"
76	"\n"
77	"attribute vec4 a_position;\n"
78	"attribute vec3 a_normal;\n"
79	"\n"
80	"varying vec3 v_color;\n"
81	"\n"
82	"float computeAttenuation(vec3 dirToLight, vec3 attenuation)\n"
83	"{\n"
84	"	float dist = length(dirToLight);\n"
85	"	return 1.0 / (attenuation.x + attenuation.y*dist + attenuation.z*dist*dist);\n"
86	"}\n"
87	"\n"
88	"vec3 computeDirLight(int ndx, vec3 position, vec3 normal)\n"
89	"{\n"
90	"	Light light = u_lights[ndx];\n"
91	"	float cosAngle = dot(light.position, normal);\n"
92	"	return cosAngle * light.diffuse;\n"
93	"}\n"
94	"\n"
95	"vec3 computeOmniLight(int ndx, vec3 position, vec3 normal)\n"
96	"{\n"
97	"	Light light = u_lights[ndx];\n"
98	"	vec3 dirToLight = light.position - position;\n"
99	"	float cosAngle = dot(normalize(dirToLight), normal);\n"
100	"	float atten = computeAttenuation(dirToLight, light.attenuation);\n"
101	"	return atten * cosAngle * light.diffuse;\n"
102	"}\n"
103	"\n"
104	"void main()\n"
105	"{\n"
106	"	vec3 lightSpacePos = vec3(u_modelviewMatrix * a_position);\n"
107	"	vec3 lightNormal = normalize(u_normalMatrix * a_normal);\n"
108	"	vec3 color = vec3(0.0);\n"
109	"	for (int i = 0; i < ${NUM_DIR_LIGHTS}; i++)\n"
110	"		color += computeDirLight(i, lightSpacePos, lightNormal);\n"
111	"	for (int i = 0; i < ${NUM_OMNI_LIGHTS}; i++)\n"
112	"		color += computeOmniLight(${NUM_DIR_LIGHTS}+i, lightSpacePos, lightNormal);\n"
113	"	v_color = color;\n"
114	"	gl_Position = u_modelviewProjectionMatrix * a_position;\n"
115	"}\n"
116;
117
118const char* s_fragmentShaderTemplate =
119	"varying highp vec3 v_color;\n"
120	"\n"
121	"void main()\n"
122	"{\n"
123	"	gl_FragColor = vec4(v_color, 1.0);\n"
124	"}\n"
125	;
126
127class LightAmountCase : public TestCase
128{
129public:
130	LightAmountCase(Context&  context, const char* name, int numDirectionalLights, int numOmniLights, int numSpotLights)
131		: TestCase(context, name, name)
132		, m_numDirectionalLights	(numDirectionalLights)
133		, m_numOmniLights			(numOmniLights)
134		, m_numSpotLights			(numSpotLights)
135	{
136	}
137
138	virtual IterateResult	iterate		(void);
139
140private:
141	int				m_numDirectionalLights;
142	int				m_numOmniLights;
143	int				m_numSpotLights;
144};
145
146TestCase::IterateResult LightAmountCase::iterate (void)
147{
148	GLU_CHECK_MSG("LightAmountTest::iterate() begin");
149
150	string vertexShaderSource;
151	string fragmentShaderSource;
152
153	// Fill in shader template parameters.
154	{
155		bool hasAnyLights = ((m_numDirectionalLights + m_numOmniLights + m_numSpotLights) != 0);
156
157		tcu::StringTemplate vertexTemplate(hasAnyLights ? s_vertexShaderTemplate : s_noLightsVertexShader);
158		tcu::StringTemplate fragmentTemplate(s_fragmentShaderTemplate);
159
160		map<string, string> params;
161		params.insert(pair<string, string>("NUM_DIR_LIGHTS", de::toString(m_numDirectionalLights)));
162		params.insert(pair<string, string>("NUM_OMNI_LIGHTS", de::toString(m_numOmniLights)));
163		params.insert(pair<string, string>("NUM_SPOT_LIGHTS", de::toString(m_numSpotLights)));
164
165		vertexShaderSource		= vertexTemplate.specialize(params);
166		fragmentShaderSource	= fragmentTemplate.specialize(params);
167	}
168
169	// Create shader and program objects.
170	glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
171	m_testCtx.getLog() << program;
172
173	// Draw something? Check results?
174	glUseProgram(program.getProgram());
175
176	bool testOk = program.isOk();
177
178	GLU_CHECK_MSG("LightAmountTest::iterate() end");
179
180	m_testCtx.setTestResult(testOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, testOk ? "Pass" : "Fail");
181	return TestCase::STOP;
182}
183
184//
185
186LightAmountTest::LightAmountTest (Context& context) : TestCaseGroup(context, "light_amount", "Light Amount Stress Tests")
187{
188}
189
190LightAmountTest::~LightAmountTest (void)
191{
192}
193
194void LightAmountTest::init (void)
195{
196	//										name				dir,	omni,	spot
197	addChild(new LightAmountCase(m_context, "none",				0,		0,		0	));
198	addChild(new LightAmountCase(m_context, "1dir",				1,		0,		0	));
199	addChild(new LightAmountCase(m_context, "2dir",				2,		0,		0	));
200	addChild(new LightAmountCase(m_context, "4dir",				4,		0,		0	));
201	addChild(new LightAmountCase(m_context, "6dir",				6,		0,		0	));
202	addChild(new LightAmountCase(m_context, "8dir",				8,		0,		0	));
203	addChild(new LightAmountCase(m_context, "10dir",			10,		0,		0	));
204	addChild(new LightAmountCase(m_context, "12dir",			12,		0,		0	));
205	addChild(new LightAmountCase(m_context, "14dir",			14,		0,		0	));
206	addChild(new LightAmountCase(m_context, "16dir",			16,		0,		0	));
207	addChild(new LightAmountCase(m_context, "1omni",			0,		1,		0	));
208	addChild(new LightAmountCase(m_context, "2omni",			0,		2,		0	));
209	addChild(new LightAmountCase(m_context, "4omni",			0,		4,		0	));
210	addChild(new LightAmountCase(m_context, "6omni",			0,		6,		0	));
211	addChild(new LightAmountCase(m_context, "8omni",			0,		8,		0	));
212	addChild(new LightAmountCase(m_context, "10omni",			0,		10,		0	));
213	addChild(new LightAmountCase(m_context, "12omni",			0,		12,		0	));
214	addChild(new LightAmountCase(m_context, "14omni",			0,		14,		0	));
215	addChild(new LightAmountCase(m_context, "16omni",			0,		16,		0	));
216// 	addChild(new LightAmountCase(m_context, "1spot",			0,		0,		1	));
217// 	addChild(new LightAmountCase(m_context, "2spot",			0,		0,		2	));
218// 	addChild(new LightAmountCase(m_context, "4spot",			0,		0,		4	));
219// 	addChild(new LightAmountCase(m_context, "6spot",			0,		0,		6	));
220// 	addChild(new LightAmountCase(m_context, "8spot",			0,		0,		8	));
221// 	addChild(new LightAmountCase(m_context, "1dir_1omni",		1,		1,		0	));
222// 	addChild(new LightAmountCase(m_context, "2dir_2omni",		2,		2,		0	));
223// 	addChild(new LightAmountCase(m_context, "4dir_4omni",		4,		4,		0	));
224// 	addChild(new LightAmountCase(m_context, "1dir_1spot",		1,		0,		1	));
225// 	addChild(new LightAmountCase(m_context, "2dir_2spot",		2,		0,		2	));
226// 	addChild(new LightAmountCase(m_context, "4dir_4spot",		4,		0,		4	));
227// 	addChild(new LightAmountCase(m_context, "1omni_1spot",		0,		1,		1	));
228// 	addChild(new LightAmountCase(m_context, "2omni_2spot",		0,		2,		2	));
229// 	addChild(new LightAmountCase(m_context, "4omni_4spot",		0,		4,		4	));
230// 	addChild(new LightAmountCase(m_context, "1dir_1omni_1spot",	1,		1,		1	));
231// 	addChild(new LightAmountCase(m_context, "2dir_2omni_2spot",	2,		2,		2	));
232// 	addChild(new LightAmountCase(m_context, "4dir_2omni_2spot",	4,		2,		2	));
233// 	addChild(new LightAmountCase(m_context, "2dir_4omni_2spot",	2,		4,		2	));
234// 	addChild(new LightAmountCase(m_context, "2dir_2omni_4spot",	2,		2,		4	));
235// 	addChild(new LightAmountCase(m_context, "4dir_4omni_4spot",	4,		4,		4	));
236}
237
238} // Functional
239} // gles2
240} // deqp
241