vr.rs revision 89e35a551ee4b0bfcb3ede10da3b027dba1da7ef
16d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme/*
26d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * Copyright (C) 2015 The Android Open Source Project
36d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
46d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
56d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * you may not use this file except in compliance with the License.
66d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * You may obtain a copy of the License at
76d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
86d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *      http://www.apache.org/licenses/LICENSE-2.0
96d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
106d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * Unless required by applicable law or agreed to in writing, software
116d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
126d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * See the License for the specific language governing permissions and
146d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * limitations under the License.
156d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */
166d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
17782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov#pragma version(1)
186d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme#pragma rs java_package_name(com.example.android.rs.vr.engine)
19d633f072552815301a559520a1f93eb7e79ba319Felipe Leme#pragma rs_fp_relaxed
20d633f072552815301a559520a1f93eb7e79ba319Felipe Leme
210f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov#define FLOAT_MAX  3.4028234E30f
22436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme#define JITTER_LENGTH 3457
230f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganovfloat jitter[JITTER_LENGTH];
246d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
256d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemefloat3 s;
26782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganovfloat3 dx;
27782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganovfloat3 dy;
28640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemefloat3 dz;
29640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemefloat zoomFactor;
3000c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganovrs_matrix4x4 matrix4;
316d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemers_matrix3x3 matrix3;
326d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeuchar4 base_color;
336d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemestatic float3 mLight;
346d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemestatic float rscale;
356d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
36640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme// material color
376d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemers_allocation opacity;
386d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemers_allocation color_map;
396d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
406d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemestatic void fillJitter() {
4100c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    for (int i = 0; i < JITTER_LENGTH; i++) {
4200c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov        jitter[i] = (rsRand(rscale)+rsRand(rscale)+rsRand(rscale))/3;
4300c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    }
446d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme}
456d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
46782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganovvoid setup_vectors() {
476d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    s = rsMatrixMultiply(&matrix4, (float3) {0.5f, 0.5f, 0.5f}).xyz;
486d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    dx = rsMatrixMultiply(&matrix3, (float3) {1.f, 0.f, 0.f});
49782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov    dy = rsMatrixMultiply(&matrix3, (float3) {0.f, 1.f, 0.f});
50640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    dz = rsMatrixMultiply(&matrix3, (float3) {0.f, 0.f, 1.f});
51640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    zoomFactor = dz.x * dz.x + dz.y * dz.y + dz.z * dz.z;
525311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    zoomFactor /= dx.x * dx.x + dx.y * dx.y + dx.z * dx.z;
5300c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    base_color.r = 0;
540f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    base_color.g = 0;
556d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    base_color.b = 0;
560f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    base_color.a = 255;
570f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
580f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    float3 mLightRelitvePos = (float3) {0.f, 0.7071f, -0.7071f}; // light relitve to camera
595311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    mLight = mLightRelitvePos.x + dx + mLightRelitvePos.y * dy + mLightRelitvePos.z * dz;
6000c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    mLight = normalize(mLight);
610f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    rscale = 1.5f/length(dz);
626d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    fillJitter();
636d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme}
646d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
65640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemestatic float triLinear(float v_0_0_0, float v_0_0_1, float v_0_1_0, float v_0_1_1,
660f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        float v_1_0_0, float v_1_0_1, float v_1_1_0, float v_1_1_1,
67436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme        float3 delta) {
68436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    float v_0_0 = mix(v_0_0_0, v_0_0_1, delta.x);
69436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    float v_0_1 = mix(v_0_1_0, v_0_1_1, delta.x);
70640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    float v_1_0 = mix(v_1_0_0, v_1_0_1, delta.x);
710f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    float v_1_1 = mix(v_1_1_0, v_1_1_1, delta.x);
72436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    float v_0 = mix(v_0_0, v_0_1, delta.y);
73436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    float v_1 = mix(v_1_0, v_1_1, delta.y);
74436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    float v = mix(v_0, v_1, delta.z);
755311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    return v;
765311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme}
775311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
785311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Lemers_allocation bricks;
795311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Lemers_allocation brick_index;
805311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Lemeint brick_dimx;
8100c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganovint brick_dimy;
8200c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganovint brick_dimz;
8300c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov
8400c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganovstatic int isInBrick(int3 p) {
8500c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    int bx = p.x >> 5;
860f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    int by = p.y >> 5;
870f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    int bz = p.z >> 5;
88436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    int brickno = bx + (by + brick_dimy * bz) * brick_dimx;
89436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
90436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    brickno *= 32 * 32;
910f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    int off = brickno + (p.z & 0x1F) * 32 + (p.y & 0x1F);
920f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    uint slice = rsGetElementAt_uint(bricks, off);
93436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    return slice & (1 << (p.x & 0x1F));
94436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme}
956d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
966d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemers_allocation volume;
976d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemers_allocation zbuff;
986d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemebool debug = true;
9900c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov
10078696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Lemeuchar4 __attribute__ ((kernel)) draw_z_buffer(float2 in, uint32_t x, uint32_t y) {
1010f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    uchar4 out = base_color;
1025311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
1035311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    float zsuface = in.x + .5f;
10400c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    float zstart = zsuface;
10500c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    float zend = in.y - 2.f;//0.5f;
10600c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    float zlen = zend - zstart;
1076d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
1086d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    if (zstart == FLOAT_MAX || zlen < 0) {
1096d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        return out;
1100f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    }
1110f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
1126d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    float3 p = s + x * dx + y * dy + dz * zstart;
1136d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    float zb = zend;
114640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    int izlen = (int) zlen;
115640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    float light = 1;
1165311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    float4 total_color = (float4) {0.f, 0.f, 0.f, 0.f};
11700c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov
1180f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    if (false) { // show the walls only used for debuging
1190f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        int3 ip = convert_int3(p);
1200f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        ip = clamp(ip, 4, 500);
1216d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        short pix = rsGetElementAt_short(volume, ip.x, ip.y, ip.z);
122eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov
12300c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov        int intensity = (((short) pix) & 0xFFFF);
124eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov        //   intensity = clamp(intensity,0,400);
1256d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
126eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov        // int op = rsGetElementAt_uchar(opacity, intensity);
127eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov
12800c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov        out.r = color.r;
1296d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        out.g = color.g;
1306d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        out.b = color.b;
1316d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        out.a = 255;
1325311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        return out;
1335311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    }
1345311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    {
1355311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        int3 ip = convert_int3(p);
1365311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
1375311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        if (isInBrick(ip)) { // isInBrick(ip)) {
1385311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
1395311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            float3 delta = p - convert_float3(ip);
1405311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            // TODO switch to rsAllocationVLoadX_short2
141640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme            // short2 tmps = rsAllocationVLoadX_short2(volume, ip.x + 0, ip.y + 0, ip.z + 0);
142436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme            //  float2 tmp =   convert_float2(tmps);
1430f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            float v_0_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 0);
144782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov            float v_0_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 0);
1450f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
14600c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov            float v_0_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
147782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov            float v_0_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
148782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov            float v_1_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 1);
149782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov            float v_1_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 1);
150782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov            float v_1_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
151782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov            float v_1_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
1520f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            float v = triLinear(v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
1530f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
154782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                    delta);
155436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme            int intensity = (((short) v) & 0xFFFF);
156640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme            uchar op = rsGetElementAt_uchar(opacity, intensity);
157782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov
158640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme            if (op != 0) { // near the surface "broken"
159782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov
160782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                float sdx = rsGetElementAt_float2(zbuff, max(0, (int) x - 1), y).x - in.x;
161782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                float sdy = rsGetElementAt_float2(zbuff, x, max(0, (int) y - 1)).x - in.x;
162640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme                float dot_prod = sqrt(1 / (1 + (sdy * sdy + sdx * sdx) * zoomFactor));
16300c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                float opf = op  * (1/255.f);
164782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
165782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                uchar4 mat = rsGetElementAt_uchar4(color_map, intensity * 2 + 1);
166436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme                float4 fcolor = convert_float4(color);;
167782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov
1680f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                float ambient = mat.x * (1/255.f);
1690f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                // float specular = mat.y * (1/255.f);
170436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme                float diffuse = mat.z * (1/255.f);
171782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                float lop = (ambient + diffuse * dot_prod) * light * opf;
17200c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                light -= opf;
173436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme                total_color += fcolor * lop;
174782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                zb = zstart;
175436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
1760f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            }
1770f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        }
1780f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    }
179436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    p += dz * jitter[(x+(y<<11))%JITTER_LENGTH];
180436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
181436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    if (light > 0) {
182436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme        for (int k = 0; k < izlen - 1; k++) {
183640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme
184640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme            int3 ip = convert_int3(p);
185640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme            if (isInBrick(ip)) {
186640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme                float3 delta = p - convert_float3(ip);
187640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme
188640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme                float v_0_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 0);
189640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme                float v_0_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 0);
19082e3793c15298f9c62edee23259c116606f10911Felipe Leme                float v_0_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
191640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme                float v_0_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
1926d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                float v_1_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 1);
1936d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                float v_1_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 1);
194782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                float v_1_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
195640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme                float v_1_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
1966d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                float v = triLinear(v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
19700c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                        v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
1985311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                        delta);
1995311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                int intensity = (((short) v) & 0xFFFF);
2006d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                uchar op = rsGetElementAt_uchar(opacity, intensity);
201640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme
2020f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                if (op != 0) {
2035311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
2045311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float3 v;
2055311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float3 vn;
2065311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
2075311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_0_0_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 0, ip.z + 0);
2085311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_0_1_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 1, ip.z + 0);
2095311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_1_0_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 0, ip.z + 1);
2105311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_1_1_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 1, ip.z + 1);
21124d5893b25ce62b7bc9ed9f35fa72b9d47f23cddFelipe Leme                    v.x = triLinear(v_0_0_1, v_0_0_2, v_0_1_1, v_0_1_2,
2125311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                            v_1_0_1, v_1_0_2, v_1_1_1, v_1_1_2,
2135311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                            delta);
2145311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
2155311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_0_0_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 0, ip.z + 0);
2165311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_0_1_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 1, ip.z + 0);
2175311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_1_0_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 0, ip.z + 1);
2185311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_1_1_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 1, ip.z + 1);
2195311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    vn.x = triLinear(v_0_0_n, v_0_0_0, v_0_1_n, v_0_1_0,
2205311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                            v_1_0_n, v_1_0_0, v_1_1_n, v_1_1_0,
2215311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                            delta);
2225311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
2235311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_0_2_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 2, ip.z + 0);
2245311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_0_2_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 2, ip.z + 0);
2255311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_1_2_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 2, ip.z + 1);
2265311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_1_2_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 2, ip.z + 1);
2275311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    v.y = triLinear(v_0_1_0, v_0_1_1, v_0_2_0, v_0_2_1,
2285311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                            v_1_1_0, v_1_1_1, v_1_2_0, v_1_2_1,
2290f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                            delta);
2300f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
2310f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float v_0_n_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
2320f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float v_0_n_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
2330f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float v_1_n_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
2340f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float v_1_n_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
2355311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    vn.y = triLinear(v_0_n_0, v_0_n_1, v_0_0_0, v_0_0_1,
2365311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                            v_1_n_0, v_1_n_1, v_1_0_0, v_1_0_1,
2370f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                            delta);
2380f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
2390f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float v_n_0_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z - 1);
2400f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float v_n_0_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z - 1);
2415311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    float v_n_1_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z - 1);
2420f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float v_n_1_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z - 1);
2430f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    vn.z = triLinear(v_n_0_0, v_n_0_1, v_n_1_0, v_n_1_1,
2440f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                            v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
2455311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                            delta);
2466d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2476d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    float v_2_0_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 2);
2486d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    float v_2_0_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 2);
2490f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float v_2_1_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 2);
25000c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                    float v_2_1_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 2);
25100c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                    v.z = triLinear(v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
25200c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                            v_2_0_0, v_2_0_1, v_2_1_0, v_2_1_1,
25300c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                            delta);
25400c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov
2556d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    float3 dv = normalize(v - vn);
2560f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float dot_prod = dot(dv, dz);
2570f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float opf = op / 255.f;
2580f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
25900c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                    uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
26024d5893b25ce62b7bc9ed9f35fa72b9d47f23cddFelipe Leme                    uchar4 mat = rsGetElementAt_uchar4(color_map, intensity * 2 + 1);
26100c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov                    float4 fcolor = convert_float4(color);;
2620f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
2636d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    // float3 mLight = (float3) {0,-1,0};
2646d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    float3 normal = dv;
2650f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float3 r = 2 * normal * dot(mLight, normal) - mLight;
2660f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    float spec = dot(r, dz);
2670f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
2680f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    // Eye point in this space is in the direction (0,0,-1)
2696d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    // Spec * Math.pow(R_z , P) lets use power == 2 (cheap)
2706d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2716d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    float ambient = mat.x * (1/255.f); // ambient
2726d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    float specular = mat.y * (1/255.f); // specular not used right now
2736d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    float diffuse = mat.z  * (1/255.f);// diffuse
2746d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    float lop = (ambient + diffuse * dot_prod + specular * pow(spec, 10)) * light * opf;
2756d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    light -= opf;
2766d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    total_color += fcolor * lop;
2776d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2786d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    zb = zstart + k;
2796d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    if (light <= 0) {
2806d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                        break;
2816d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                    }
2826d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme                }
283eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov            }
28400c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov
28500c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov            p += dz;
2865311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        }
2870f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    }
2886d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2896d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    out = convert_uchar4(clamp(total_color, 0.f, 255.f));
290782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov    out.a = 0xFF;
2916d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2920f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    return out;
2930f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov}
2940f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov