From: Nozomi Kodama Subject: d3dx9_36 [patch 3/3]: Implement D3DXSHEvalSphericalLight Message-Id: <1352876953.62467.YahooMailNeo@web132303.mail.ird.yahoo.com> Date: Wed, 14 Nov 2012 07:09:13 +0000 (GMT)
From 981f9f72dcb7593d0de904c8868a654e0fb26bfd Mon Sep 17 00:00:00 2001 From: Nozomi Kodama Date: Tue, 13 Nov 2012 21:00:17 -1000 Subject: Implement D3DXSHEvalSphericalLight --- dlls/d3dx9_36/d3dx9_36.spec | 2 +- dlls/d3dx9_36/math.c | 38 +++++++++++ dlls/d3dx9_36/tests/math.c | 152 +++++++++++++++++++++++++++++++++++++++++++ include/d3dx9math.h | 1 + 4 files changed, 192 insertions(+), 1 deletion(-) diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index 8510c33..6efa954 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -278,7 +278,7 @@ @ stdcall D3DXSHEvalDirection(ptr long ptr) @ stdcall D3DXSHEvalDirectionalLight(long ptr float float float ptr ptr ptr) @ stdcall D3DXSHEvalHemisphereLight(long ptr int128 int128 ptr ptr ptr) -@ stub D3DXSHEvalSphericalLight(long ptr long long long long ptr ptr ptr) +@ stdcall D3DXSHEvalSphericalLight(long ptr float float float float ptr ptr ptr) @ stdcall D3DXSHMultiply2(ptr ptr ptr) @ stdcall D3DXSHMultiply3(ptr ptr ptr) @ stdcall D3DXSHMultiply4(ptr ptr ptr) diff --git a/dlls/d3dx9_36/math.c b/dlls/d3dx9_36/math.c index 33aca41..806210b 100644 --- a/dlls/d3dx9_36/math.c +++ b/dlls/d3dx9_36/math.c @@ -2432,6 +2432,44 @@ HRESULT WINAPI D3DXSHEvalHemisphereLight(UINT order, CONST D3DXVECTOR3 *dir, D3D return D3D_OK; } +HRESULT WINAPI D3DXSHEvalSphericalLight(UINT order, CONST D3DXVECTOR3 *dir, FLOAT radius, + FLOAT Rintensity, FLOAT Gintensity, FLOAT Bintensity, FLOAT *rout, FLOAT *gout, FLOAT *bout) +{ + D3DXVECTOR3 normal; + FLOAT cap[6], clamped_angle, dist, temp; + UINT i, index, j; + + TRACE("order %u, dir %p, radius %f, red %f, green %f, blue %f, rout %p, gout %p, bout %p\n", + order, dir, radius, Rintensity, Gintensity, Bintensity, rout, gout, bout); + + if (radius < 0.0f) + radius = -radius; + + dist = D3DXVec3Length(dir); + clamped_angle = (dist <= radius) ? D3DX_PI / 2.0f : asinf(radius / dist); + + weightedcapintegrale(cap, order, clamped_angle); + D3DXVec3Normalize(&normal, dir); + D3DXSHEvalDirection(rout, order, &normal); + + for (i = 0; i < order; i++) + { + for (j = 0; j < 2 * i + 1; j++) + { + index = i * i + j; + temp = rout[index] * cap[i]; + + rout[index] = temp * Rintensity; + if (gout) + gout[index] = temp * Gintensity; + if (bout) + bout[index] = temp * Bintensity; + } + } + + return D3D_OK; +} + FLOAT * WINAPI D3DXSHMultiply2(FLOAT *out, const FLOAT *a, const FLOAT *b) { FLOAT ta, tb; diff --git a/dlls/d3dx9_36/tests/math.c b/dlls/d3dx9_36/tests/math.c index 9d9139c..f78f03c 100644 --- a/dlls/d3dx9_36/tests/math.c +++ b/dlls/d3dx9_36/tests/math.c @@ -2911,6 +2911,157 @@ static void test_D3DXSHEvalHemisphereLight(void) } } +static void test_D3DXSHEvalSphericalLight(void) +{ + D3DXVECTOR3 dir; + FLOAT *blue_out, bout[49], expected, gout[49], *green_out, *red_out, rout[49]; + const FLOAT table[] = { + /* Red colour */ + 3.01317239f, -0.97724032f, 2.24765277f, -0.89580363f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.06292814f, -0.42737406f, 0.61921263f, + -0.30450898f, 0.56761158f, 0.03723336f, -0.08191673f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, -0.0f, 0.0f, 0.0f, + 0.0f, 0.01249927f, -0.01374878f, -0.14810932f, 0.43434596f, -0.24598616f, + -0.15175794f, -0.22548729f, -0.03784076f, 0.19280137f, -0.07830712f, 0.00797894f, + + 0.40251964f, -0.24365333f, 0.56040263f, -0.22334887f, 0.16204689f, -0.40659040f, + 0.44600141f, -0.37270784f, -0.01411773f, -0.04319951f, 0.29338786f, -0.42508304f, + 0.20904225f, -0.38965943f, -0.02556031f, 0.05623499f, -0.00468823f, -0.07920021f, + 0.33171222f, -0.30782884f, 0.00052908f, -0.28217643f, -0.02889918f, 0.10309891f, + -0.02670213f, 0.00724340f, -0.00796750f, -0.08583023f, 0.25170606f, -0.14255044f, + -0.08794463f, -0.13067122f, -0.02192894f, 0.11172954f, -0.04537944f, 0.00462384f, + + 1.95445275f, -0.85659367f, 1.97016549f, -0.78521085f, 0.23103346f, -0.57968396f, + 0.63587302f, -0.53137696f, -0.02012792f, 0.02111043f, -0.14337072f, 0.20772660f, + -0.10215330f, 0.19041604f, 0.01249063f, -0.02748052f, 0.00633162f, 0.10696279f, + -0.44798949f, 0.41573414f, -0.00071454f, 0.38108963f, 0.03902940f, -0.13923886f, + 0.03606220f, -0.00447360f, 0.00492081f, 0.05300967f, -0.15545636f, 0.08804068f, + 0.05431554f, 0.08070395f, 0.01354355f, -0.06900536f, 0.02802683f, -0.00285574f, + /* Green colour */ + 4.60838127f, -1.49460280f, 3.43758631f, -1.37005258f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.09624302f, -0.65363091f, 0.94703102f, + -0.46571958f, 0.86811179f, 0.05694513f, -0.12528442f, -0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.01911653f, -0.02102755f, -0.22652012f, 0.66429377f, -0.37621412f, + -0.23210037f, -0.34486291f, -0.05787410f, 0.29487267f, -0.11976383f, 0.01220309f, + + 0.61561823f, -0.37264627f, 0.85708636f, -0.34159240f, 0.24783641f, -0.62184411f, + 0.68211979f, -0.57002378f, -0.02159182f, -0.06606984f, 0.44871080f, -0.65012693f, + 0.31971166f, -0.59594971f, -0.03909224f, 0.08600645f, -0.00717023f, -0.12112973f, + 0.50732452f, -0.47079703f, 0.00080918f, -0.43156394f, -0.04419874f, 0.15768069f, + -0.04083854f, 0.01107814f, -0.01218559f, -0.13126975f, 0.38496217f, -0.21801829f, + -0.13450353f, -0.19985008f, -0.03353838f, 0.17088045f, -0.06940385f, 0.00707176f, + + 2.98916292f, -1.31008446f, 3.01319408f, -1.20091069f, 0.35334525f, -0.88657540f, + 0.97251165f, -0.81269407f, -0.03078388f, 0.03228654f, -0.21927285f, 0.31769949f, + -0.15623444f, 0.29122451f, 0.01910332f, -0.04202903f, 0.00968366f, 0.16359015f, + -0.68516040f, 0.63582867f, -0.00109283f, 0.58284295f, 0.05969203f, -0.21295355f, + 0.05515395f, -0.00684198f, 0.00752595f, 0.08107361f, -0.23775679f, 0.13465045f, + 0.08307083f, 0.12342957f, 0.02071366f, -0.10553761f, 0.04286456f, -0.00436760f, + /* Blue colour */ + 6.20359039f, -2.01196527f, 4.62752008f, -1.84430146f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.12955792f, -0.87988776f, 1.27484941f, + -0.62693024f, 1.16861200f, 0.07665691f, -0.16865209f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.02573379f, -0.02830632f, -0.30493096f, 0.89424169f, -0.50644207f, + -0.31244281f, -0.46423855f, -0.07790744f, 0.39694402f, -0.16122055f, 0.01642723f, + + 0.82871687f, -0.50163919f, 1.15377009f, -0.45983589f, 0.33362597f, -0.83709794f, + 0.91823828f, -0.76733971f, -0.02906591f, -0.08894017f, 0.60403383f, -0.87517095f, + 0.43038112f, -0.80224001f, -0.05262417f, 0.11577792f, -0.00965224f, -0.16305926f, + 0.68293691f, -0.63376528f, 0.00108928f, -0.58095151f, -0.05949831f, 0.21226248f, + -0.05497497f, 0.01491288f, -0.01640368f, -0.17670928f, 0.51821834f, -0.29348618f, + -0.18106246f, -0.26902896f, -0.04514782f, 0.23003140f, -0.09342826f, 0.00951968f, + + 4.02387333f, -1.76357520f, 4.05622292f, -1.61661065f, 0.47565711f, -1.19346702f, + 1.30915034f, -1.09401131f, -0.04143983f, 0.04346266f, -0.29517499f, 0.42767239f, + -0.21031560f, 0.39203301f, 0.02571601f, -0.05657754f, 0.01303570f, 0.22021750f, + -0.92233127f, 0.85592318f, -0.00147112f, 0.78459626f, 0.08035465f, -0.28666824f, + 0.07424571f, -0.00921036f, 0.01013109f, 0.10913756f, -0.32005721f, 0.18126021f, + 0.11182612f, 0.16615519f, 0.02788378f, -0.14206986f, 0.05770230f, -0.00587946f, }; + struct + { + FLOAT *red_in, *green_in, *blue_in; + const FLOAT *red_out, *green_out, *blue_out; + FLOAT radius, roffset, goffset, boffset; + } test[] = + { { rout, gout, bout, table, &table[108], &table[216], 17.4f, 1.01f, 1.02f, 1.03f, }, + { rout, gout, bout, &table[36], &table[144], &table[252], 1.6f, 1.01f, 1.02f, 1.03f, }, + { rout, gout, bout, &table[72], &table[180], &table[288], -3.0f, 1.01f, 1.02f, 1.03f, }, + { rout, rout, rout, &table[216], &table[216], &table[216], 17.4f, 1.03f, 1.03f, 1.03f, }, + { rout, rout, bout, &table[108], &table[108], &table[216], 17.4, 1.02f, 1.02f, 1.03f, }, + { rout, gout, gout, table, &table[216], &table[216], 17.4f, 1.01f, 1.03f, 1.03f, }, + { rout, gout, rout, &table[216], &table[108], &table[216], 17.4f, 1.03f, 1.02f, 1.03f, }, + /* D3DXSHEvalSphericalLight accepts NULL green or blue colour. */ + { rout, NULL, bout, table, NULL, &table[216], 17.4f, 1.01f, 0.0f, 1.03f, }, + { rout, gout, NULL, table, &table[108], NULL, 17.4f, 1.01f, 1.02f, 0.0f, }, + { rout, NULL, NULL, table, NULL, NULL, 17.4f, 1.01f, 0.0f, 0.0f, }, }; + HRESULT hr; + unsigned int j, l, order; + + dir.x = 1.1f; dir.y= 1.2f; dir.z = 2.76f; + + for (l = 0; l < sizeof(test) / sizeof(test[0]); l++) + { + for (order = D3DXSH_MINORDER; order <= D3DXSH_MAXORDER; order++) + { + red_out = test[l].red_in; + green_out = test[l].green_in; + blue_out = test[l].blue_in; + + for (j = 0; j < 49; j++) + { + red_out[j] = 1.01f + j; + if (green_out) + green_out[j] = 1.02f + j; + if (blue_out) + blue_out[j] = 1.03f + j; + } + + hr = D3DXSHEvalSphericalLight(order, &dir, test[l].radius, 1.7f, 2.6f, 3.5f, red_out, green_out, blue_out); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + + for (j = 0; j < 49; j++) + { + if (j >= order * order) + expected = j + test[l].roffset; + else + expected = test[l].red_out[j]; + ok(relative_error(expected, red_out[j]) < admitted_error, + "Red: case %u, order %u: expected[%u] = %f, received %f\n", l, order, j, expected, red_out[j]); + + if (green_out) + { + if (j >= order * order) + expected = j + test[l].goffset; + else + expected = test[l].green_out[j]; + ok(relative_error(expected, green_out[j]) < admitted_error, + "Green: case %u, order %u: expected[%u] = %f, received %f\n", l, order, j, expected, green_out[j]); + } + + if (blue_out) + { + if (j >= order * order) + expected = j + test[l].boffset; + else + expected = test[l].blue_out[j]; + ok(relative_error(expected, blue_out[j]) < admitted_error, + "Blue: case %u, order %u: expected[%u] = %f, received %f\n", l, order, j, expected, blue_out[j]); + } + } + } + } + + /* D3DXSHEvalSphericalLight accepts order < D3DXSH_MINORDER or order > D3DXSH_MAXORDER. But tests in native windows show that the colour outputs are not set */ + hr = D3DXSHEvalSphericalLight(7, &dir, 17.4f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + hr = D3DXSHEvalSphericalLight(0, &dir, 17.4f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + hr = D3DXSHEvalSphericalLight(1, &dir, 17.4f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); +} + static void test_D3DXSHMultiply2(void) { unsigned int i; @@ -3257,6 +3408,7 @@ START_TEST(math) test_D3DXSHEvalDirection(); test_D3DXSHEvalDirectionalLight(); test_D3DXSHEvalHemisphereLight(); + test_D3DXSHEvalSphericalLight(); test_D3DXSHMultiply2(); test_D3DXSHMultiply3(); test_D3DXSHMultiply4(); diff --git a/include/d3dx9math.h b/include/d3dx9math.h index 0167dfe..daaea4c 100644 --- a/include/d3dx9math.h +++ b/include/d3dx9math.h @@ -383,6 +383,7 @@ HRESULT WINAPI D3DXSHEvalConeLight(UINT order, CONST D3DXVECTOR3 *dir, FLOAT rad FLOAT* WINAPI D3DXSHEvalDirection(FLOAT *out, UINT order, CONST D3DXVECTOR3 *dir); HRESULT WINAPI D3DXSHEvalDirectionalLight(UINT order, CONST D3DXVECTOR3 *dir, FLOAT Rintensity, FLOAT Gintensity, FLOAT Bintensity, FLOAT *rout, FLOAT *gout, FLOAT *bout); HRESULT WINAPI D3DXSHEvalHemisphereLight(UINT order, CONST D3DXVECTOR3 *dir, D3DXCOLOR top, D3DXCOLOR bottom, FLOAT *rout, FLOAT *gout, FLOAT *bout); +HRESULT WINAPI D3DXSHEvalSphericalLight(UINT order, CONST D3DXVECTOR3 *dir, FLOAT radius, FLOAT Rintensity, FLOAT Gintensity, FLOAT Bintensity, FLOAT *rout, FLOAT *gout, FLOAT *bout); FLOAT* WINAPI D3DXSHMultiply2(FLOAT *out, CONST FLOAT *a, CONST FLOAT *b); FLOAT* WINAPI D3DXSHMultiply3(FLOAT *out, CONST FLOAT *a, CONST FLOAT *b); FLOAT* WINAPI D3DXSHMultiply4(FLOAT *out, CONST FLOAT *a, CONST FLOAT *b); -- 1.7.10.4