15b539461dcc159bd89297443780d635ccc5e3564John Hoford/*
25b539461dcc159bd89297443780d635ccc5e3564John Hoford * Copyright (C) 2015 The Android Open Source Project
35b539461dcc159bd89297443780d635ccc5e3564John Hoford *
45b539461dcc159bd89297443780d635ccc5e3564John Hoford * Licensed under the Apache License, Version 2.0 (the "License");
55b539461dcc159bd89297443780d635ccc5e3564John Hoford * you may not use this file except in compliance with the License.
65b539461dcc159bd89297443780d635ccc5e3564John Hoford * You may obtain a copy of the License at
75b539461dcc159bd89297443780d635ccc5e3564John Hoford *
85b539461dcc159bd89297443780d635ccc5e3564John Hoford *      http://www.apache.org/licenses/LICENSE-2.0
95b539461dcc159bd89297443780d635ccc5e3564John Hoford *
105b539461dcc159bd89297443780d635ccc5e3564John Hoford * Unless required by applicable law or agreed to in writing, software
115b539461dcc159bd89297443780d635ccc5e3564John Hoford * distributed under the License is distributed on an "AS IS" BASIS,
125b539461dcc159bd89297443780d635ccc5e3564John Hoford * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135b539461dcc159bd89297443780d635ccc5e3564John Hoford * See the License for the specific language governing permissions and
145b539461dcc159bd89297443780d635ccc5e3564John Hoford * limitations under the License.
155b539461dcc159bd89297443780d635ccc5e3564John Hoford */
165b539461dcc159bd89297443780d635ccc5e3564John Hoford
175b539461dcc159bd89297443780d635ccc5e3564John Hoford#pragma version(1)
185b539461dcc159bd89297443780d635ccc5e3564John Hoford#pragma rs java_package_name(com.example.android.rs.vr.engine)
195b539461dcc159bd89297443780d635ccc5e3564John Hoford#pragma rs_fp_relaxed
205b539461dcc159bd89297443780d635ccc5e3564John Hoford
215b539461dcc159bd89297443780d635ccc5e3564John Hoford#define FLOAT_MAX  3.4028234E30f
22c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford#define JITTER_LENGTH 3457
235b539461dcc159bd89297443780d635ccc5e3564John Hofordfloat jitter[JITTER_LENGTH];
245b539461dcc159bd89297443780d635ccc5e3564John Hoford
255b539461dcc159bd89297443780d635ccc5e3564John Hofordfloat3 s;
265b539461dcc159bd89297443780d635ccc5e3564John Hofordfloat3 dx;
275b539461dcc159bd89297443780d635ccc5e3564John Hofordfloat3 dy;
285b539461dcc159bd89297443780d635ccc5e3564John Hofordfloat3 dz;
295b539461dcc159bd89297443780d635ccc5e3564John Hofordfloat zoomFactor;
305b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_matrix4x4 matrix4;
315b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_matrix3x3 matrix3;
325b539461dcc159bd89297443780d635ccc5e3564John Hoforduchar4 base_color;
335b539461dcc159bd89297443780d635ccc5e3564John Hofordstatic float3 mLight;
34c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hofordstatic float rscale;
355b539461dcc159bd89297443780d635ccc5e3564John Hoford
365b539461dcc159bd89297443780d635ccc5e3564John Hoford// material color
375b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation opacity;
385b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation color_map;
395b539461dcc159bd89297443780d635ccc5e3564John Hoford
405b539461dcc159bd89297443780d635ccc5e3564John Hofordstatic void fillJitter() {
415b539461dcc159bd89297443780d635ccc5e3564John Hoford    for (int i = 0; i < JITTER_LENGTH; i++) {
42c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford        jitter[i] = (rsRand(rscale)+rsRand(rscale)+rsRand(rscale))/3;
435b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
445b539461dcc159bd89297443780d635ccc5e3564John Hoford}
455b539461dcc159bd89297443780d635ccc5e3564John Hoford
465b539461dcc159bd89297443780d635ccc5e3564John Hofordvoid setup_vectors() {
475b539461dcc159bd89297443780d635ccc5e3564John Hoford    s = rsMatrixMultiply(&matrix4, (float3) {0.5f, 0.5f, 0.5f}).xyz;
485b539461dcc159bd89297443780d635ccc5e3564John Hoford    dx = rsMatrixMultiply(&matrix3, (float3) {1.f, 0.f, 0.f});
495b539461dcc159bd89297443780d635ccc5e3564John Hoford    dy = rsMatrixMultiply(&matrix3, (float3) {0.f, 1.f, 0.f});
505b539461dcc159bd89297443780d635ccc5e3564John Hoford    dz = rsMatrixMultiply(&matrix3, (float3) {0.f, 0.f, 1.f});
515b539461dcc159bd89297443780d635ccc5e3564John Hoford    zoomFactor = dz.x * dz.x + dz.y * dz.y + dz.z * dz.z;
525b539461dcc159bd89297443780d635ccc5e3564John Hoford    zoomFactor /= dx.x * dx.x + dx.y * dx.y + dx.z * dx.z;
535b539461dcc159bd89297443780d635ccc5e3564John Hoford    base_color.r = 0;
545b539461dcc159bd89297443780d635ccc5e3564John Hoford    base_color.g = 0;
555b539461dcc159bd89297443780d635ccc5e3564John Hoford    base_color.b = 0;
565b539461dcc159bd89297443780d635ccc5e3564John Hoford    base_color.a = 255;
57c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford
58c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford    float3 mLightRelitvePos = (float3) {0.f, 0.7071f, -0.7071f}; // light relitve to camera
595b539461dcc159bd89297443780d635ccc5e3564John Hoford    mLight = mLightRelitvePos.x + dx + mLightRelitvePos.y * dy + mLightRelitvePos.z * dz;
605b539461dcc159bd89297443780d635ccc5e3564John Hoford    mLight = normalize(mLight);
61c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford    rscale = 1.5f/length(dz);
62c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford    fillJitter();
635b539461dcc159bd89297443780d635ccc5e3564John Hoford}
645b539461dcc159bd89297443780d635ccc5e3564John Hoford
65c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hofordstatic float triLinear(float v_0_0_0, float v_0_0_1, float v_0_1_0, float v_0_1_1,
665b539461dcc159bd89297443780d635ccc5e3564John Hoford        float v_1_0_0, float v_1_0_1, float v_1_1_0, float v_1_1_1,
675b539461dcc159bd89297443780d635ccc5e3564John Hoford        float3 delta) {
685b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0_0 = mix(v_0_0_0, v_0_0_1, delta.x);
695b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0_1 = mix(v_0_1_0, v_0_1_1, delta.x);
705b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1_0 = mix(v_1_0_0, v_1_0_1, delta.x);
715b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1_1 = mix(v_1_1_0, v_1_1_1, delta.x);
725b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0 = mix(v_0_0, v_0_1, delta.y);
735b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1 = mix(v_1_0, v_1_1, delta.y);
745b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v = mix(v_0, v_1, delta.z);
755b539461dcc159bd89297443780d635ccc5e3564John Hoford    return v;
765b539461dcc159bd89297443780d635ccc5e3564John Hoford}
775b539461dcc159bd89297443780d635ccc5e3564John Hoford
785b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation bricks;
795b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation brick_index;
805b539461dcc159bd89297443780d635ccc5e3564John Hofordint brick_dimx;
815b539461dcc159bd89297443780d635ccc5e3564John Hofordint brick_dimy;
825b539461dcc159bd89297443780d635ccc5e3564John Hofordint brick_dimz;
835b539461dcc159bd89297443780d635ccc5e3564John Hoford
845b539461dcc159bd89297443780d635ccc5e3564John Hofordstatic int isInBrick(int3 p) {
855b539461dcc159bd89297443780d635ccc5e3564John Hoford    int bx = p.x >> 5;
865b539461dcc159bd89297443780d635ccc5e3564John Hoford    int by = p.y >> 5;
875b539461dcc159bd89297443780d635ccc5e3564John Hoford    int bz = p.z >> 5;
885b539461dcc159bd89297443780d635ccc5e3564John Hoford    int brickno = bx + (by + brick_dimy * bz) * brick_dimx;
895b539461dcc159bd89297443780d635ccc5e3564John Hoford
905b539461dcc159bd89297443780d635ccc5e3564John Hoford    brickno *= 32 * 32;
915b539461dcc159bd89297443780d635ccc5e3564John Hoford    int off = brickno + (p.z & 0x1F) * 32 + (p.y & 0x1F);
925b539461dcc159bd89297443780d635ccc5e3564John Hoford    uint slice = rsGetElementAt_uint(bricks, off);
935b539461dcc159bd89297443780d635ccc5e3564John Hoford    return slice & (1 << (p.x & 0x1F));
945b539461dcc159bd89297443780d635ccc5e3564John Hoford}
955b539461dcc159bd89297443780d635ccc5e3564John Hoford
965b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation volume;
975b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation zbuff;
985b539461dcc159bd89297443780d635ccc5e3564John Hofordbool debug = true;
995b539461dcc159bd89297443780d635ccc5e3564John Hoford
1005b539461dcc159bd89297443780d635ccc5e3564John Hoforduchar4 __attribute__ ((kernel)) draw_z_buffer(float2 in, uint32_t x, uint32_t y) {
1015b539461dcc159bd89297443780d635ccc5e3564John Hoford    uchar4 out = base_color;
1025b539461dcc159bd89297443780d635ccc5e3564John Hoford
1035b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zsuface = in.x + .5f;
1045b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zstart = zsuface;
1055b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zend = in.y - 2.f;//0.5f;
1065b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zlen = zend - zstart;
1075b539461dcc159bd89297443780d635ccc5e3564John Hoford
1085b539461dcc159bd89297443780d635ccc5e3564John Hoford    if (zstart == FLOAT_MAX || zlen < 0) {
1095b539461dcc159bd89297443780d635ccc5e3564John Hoford        return out;
1105b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
1115b539461dcc159bd89297443780d635ccc5e3564John Hoford
1125b539461dcc159bd89297443780d635ccc5e3564John Hoford    float3 p = s + x * dx + y * dy + dz * zstart;
1135b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zb = zend;
1145b539461dcc159bd89297443780d635ccc5e3564John Hoford    int izlen = (int) zlen;
1155b539461dcc159bd89297443780d635ccc5e3564John Hoford    float light = 1;
1165b539461dcc159bd89297443780d635ccc5e3564John Hoford    float4 total_color = (float4) {0.f, 0.f, 0.f, 0.f};
1175b539461dcc159bd89297443780d635ccc5e3564John Hoford
1185b539461dcc159bd89297443780d635ccc5e3564John Hoford    if (false) { // show the walls only used for debuging
1195b539461dcc159bd89297443780d635ccc5e3564John Hoford        int3 ip = convert_int3(p);
1205b539461dcc159bd89297443780d635ccc5e3564John Hoford        ip = clamp(ip, 4, 500);
1215b539461dcc159bd89297443780d635ccc5e3564John Hoford        short pix = rsGetElementAt_short(volume, ip.x, ip.y, ip.z);
1225b539461dcc159bd89297443780d635ccc5e3564John Hoford
1235b539461dcc159bd89297443780d635ccc5e3564John Hoford        int intensity = (((short) pix) & 0xFFFF);
1245b539461dcc159bd89297443780d635ccc5e3564John Hoford        //   intensity = clamp(intensity,0,400);
1255b539461dcc159bd89297443780d635ccc5e3564John Hoford        uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
126de235208fd6bcaa29c95404d990f7b5e212435f9Jean-Luc Brouillet        // int op = rsGetElementAt_uchar(opacity, intensity);
1275b539461dcc159bd89297443780d635ccc5e3564John Hoford
1285b539461dcc159bd89297443780d635ccc5e3564John Hoford        out.r = color.r;
1295b539461dcc159bd89297443780d635ccc5e3564John Hoford        out.g = color.g;
1305b539461dcc159bd89297443780d635ccc5e3564John Hoford        out.b = color.b;
1315b539461dcc159bd89297443780d635ccc5e3564John Hoford        out.a = 255;
1325b539461dcc159bd89297443780d635ccc5e3564John Hoford        return out;
1335b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
1345b539461dcc159bd89297443780d635ccc5e3564John Hoford    {
1355b539461dcc159bd89297443780d635ccc5e3564John Hoford        int3 ip = convert_int3(p);
1365b539461dcc159bd89297443780d635ccc5e3564John Hoford
1375b539461dcc159bd89297443780d635ccc5e3564John Hoford        if (isInBrick(ip)) { // isInBrick(ip)) {
1385b539461dcc159bd89297443780d635ccc5e3564John Hoford
1395b539461dcc159bd89297443780d635ccc5e3564John Hoford            float3 delta = p - convert_float3(ip);
1405b539461dcc159bd89297443780d635ccc5e3564John Hoford            // TODO switch to rsAllocationVLoadX_short2
1415b539461dcc159bd89297443780d635ccc5e3564John Hoford            // short2 tmps = rsAllocationVLoadX_short2(volume, ip.x + 0, ip.y + 0, ip.z + 0);
1425b539461dcc159bd89297443780d635ccc5e3564John Hoford            //  float2 tmp =   convert_float2(tmps);
1435b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_0_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 0);
1445b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_0_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 0);
1455b539461dcc159bd89297443780d635ccc5e3564John Hoford
1465b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_0_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
1475b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_0_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
1485b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_1_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 1);
1495b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_1_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 1);
1505b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_1_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
1515b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_1_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
1525b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v = triLinear(v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
1535b539461dcc159bd89297443780d635ccc5e3564John Hoford                    v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
1545b539461dcc159bd89297443780d635ccc5e3564John Hoford                    delta);
1555b539461dcc159bd89297443780d635ccc5e3564John Hoford            int intensity = (((short) v) & 0xFFFF);
1565b539461dcc159bd89297443780d635ccc5e3564John Hoford            uchar op = rsGetElementAt_uchar(opacity, intensity);
1575b539461dcc159bd89297443780d635ccc5e3564John Hoford
1585b539461dcc159bd89297443780d635ccc5e3564John Hoford            if (op != 0) { // near the surface "broken"
1595b539461dcc159bd89297443780d635ccc5e3564John Hoford
1605b539461dcc159bd89297443780d635ccc5e3564John Hoford                float sdx = rsGetElementAt_float2(zbuff, max(0, (int) x - 1), y).x - in.x;
1615b539461dcc159bd89297443780d635ccc5e3564John Hoford                float sdy = rsGetElementAt_float2(zbuff, x, max(0, (int) y - 1)).x - in.x;
1625b539461dcc159bd89297443780d635ccc5e3564John Hoford                float dot_prod = sqrt(1 / (1 + (sdy * sdy + sdx * sdx) * zoomFactor));
163c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford                float opf = op  * (1/255.f);
1645b539461dcc159bd89297443780d635ccc5e3564John Hoford                uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
1655b539461dcc159bd89297443780d635ccc5e3564John Hoford                uchar4 mat = rsGetElementAt_uchar4(color_map, intensity * 2 + 1);
1665b539461dcc159bd89297443780d635ccc5e3564John Hoford                float4 fcolor = convert_float4(color);;
1675b539461dcc159bd89297443780d635ccc5e3564John Hoford
168c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford                float ambient = mat.x * (1/255.f);
169de235208fd6bcaa29c95404d990f7b5e212435f9Jean-Luc Brouillet                // float specular = mat.y * (1/255.f);
170c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford                float diffuse = mat.z * (1/255.f);
1715b539461dcc159bd89297443780d635ccc5e3564John Hoford                float lop = (ambient + diffuse * dot_prod) * light * opf;
1725b539461dcc159bd89297443780d635ccc5e3564John Hoford                light -= opf;
1735b539461dcc159bd89297443780d635ccc5e3564John Hoford                total_color += fcolor * lop;
1745b539461dcc159bd89297443780d635ccc5e3564John Hoford                zb = zstart;
1755b539461dcc159bd89297443780d635ccc5e3564John Hoford
1765b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
1775b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
1785b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
179c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford    p += dz * jitter[(x+(y<<11))%JITTER_LENGTH];
1805b539461dcc159bd89297443780d635ccc5e3564John Hoford
1815b539461dcc159bd89297443780d635ccc5e3564John Hoford    if (light > 0) {
1825b539461dcc159bd89297443780d635ccc5e3564John Hoford        for (int k = 0; k < izlen - 1; k++) {
1835b539461dcc159bd89297443780d635ccc5e3564John Hoford
1845b539461dcc159bd89297443780d635ccc5e3564John Hoford            int3 ip = convert_int3(p);
1855b539461dcc159bd89297443780d635ccc5e3564John Hoford            if (isInBrick(ip)) {
1865b539461dcc159bd89297443780d635ccc5e3564John Hoford                float3 delta = p - convert_float3(ip);
1875b539461dcc159bd89297443780d635ccc5e3564John Hoford
1885b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_0_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 0);
1895b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_0_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 0);
1905b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_0_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
1915b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_0_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
1925b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_1_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 1);
1935b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_1_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 1);
1945b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_1_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
1955b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_1_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
1965b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v = triLinear(v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
1975b539461dcc159bd89297443780d635ccc5e3564John Hoford                        v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
1985b539461dcc159bd89297443780d635ccc5e3564John Hoford                        delta);
1995b539461dcc159bd89297443780d635ccc5e3564John Hoford                int intensity = (((short) v) & 0xFFFF);
2005b539461dcc159bd89297443780d635ccc5e3564John Hoford                uchar op = rsGetElementAt_uchar(opacity, intensity);
2015b539461dcc159bd89297443780d635ccc5e3564John Hoford
2025b539461dcc159bd89297443780d635ccc5e3564John Hoford                if (op != 0) {
2035b539461dcc159bd89297443780d635ccc5e3564John Hoford
2045b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 v;
2055b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 vn;
2065b539461dcc159bd89297443780d635ccc5e3564John Hoford
2075b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_0_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 0, ip.z + 0);
2085b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_1_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 1, ip.z + 0);
2095b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_0_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 0, ip.z + 1);
2105b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_1_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 1, ip.z + 1);
2115b539461dcc159bd89297443780d635ccc5e3564John Hoford                    v.x = triLinear(v_0_0_1, v_0_0_2, v_0_1_1, v_0_1_2,
2125b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_1_0_1, v_1_0_2, v_1_1_1, v_1_1_2,
2135b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2145b539461dcc159bd89297443780d635ccc5e3564John Hoford
2155b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_0_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 0, ip.z + 0);
2165b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_1_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 1, ip.z + 0);
2175b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_0_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 0, ip.z + 1);
2185b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_1_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 1, ip.z + 1);
2195b539461dcc159bd89297443780d635ccc5e3564John Hoford                    vn.x = triLinear(v_0_0_n, v_0_0_0, v_0_1_n, v_0_1_0,
2205b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_1_0_n, v_1_0_0, v_1_1_n, v_1_1_0,
2215b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2225b539461dcc159bd89297443780d635ccc5e3564John Hoford
2235b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_2_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 2, ip.z + 0);
2245b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_2_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 2, ip.z + 0);
2255b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_2_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 2, ip.z + 1);
2265b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_2_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 2, ip.z + 1);
2275b539461dcc159bd89297443780d635ccc5e3564John Hoford                    v.y = triLinear(v_0_1_0, v_0_1_1, v_0_2_0, v_0_2_1,
2285b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_1_1_0, v_1_1_1, v_1_2_0, v_1_2_1,
2295b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2305b539461dcc159bd89297443780d635ccc5e3564John Hoford
2315b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_n_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
2325b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_n_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
2335b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_n_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
2345b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_n_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
2355b539461dcc159bd89297443780d635ccc5e3564John Hoford                    vn.y = triLinear(v_0_n_0, v_0_n_1, v_0_0_0, v_0_0_1,
2365b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_1_n_0, v_1_n_1, v_1_0_0, v_1_0_1,
2375b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2385b539461dcc159bd89297443780d635ccc5e3564John Hoford
2395b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_n_0_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z - 1);
2405b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_n_0_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z - 1);
2415b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_n_1_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z - 1);
2425b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_n_1_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z - 1);
2435b539461dcc159bd89297443780d635ccc5e3564John Hoford                    vn.z = triLinear(v_n_0_0, v_n_0_1, v_n_1_0, v_n_1_1,
2445b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
2455b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2465b539461dcc159bd89297443780d635ccc5e3564John Hoford
2475b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_2_0_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 2);
2485b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_2_0_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 2);
2495b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_2_1_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 2);
2505b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_2_1_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 2);
2515b539461dcc159bd89297443780d635ccc5e3564John Hoford                    v.z = triLinear(v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
2525b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_2_0_0, v_2_0_1, v_2_1_0, v_2_1_1,
2535b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2545b539461dcc159bd89297443780d635ccc5e3564John Hoford
2555b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 dv = normalize(v - vn);
2565b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float dot_prod = dot(dv, dz);
2575b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float opf = op / 255.f;
2585b539461dcc159bd89297443780d635ccc5e3564John Hoford
2595b539461dcc159bd89297443780d635ccc5e3564John Hoford                    uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
2605b539461dcc159bd89297443780d635ccc5e3564John Hoford                    uchar4 mat = rsGetElementAt_uchar4(color_map, intensity * 2 + 1);
2615b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float4 fcolor = convert_float4(color);;
2625b539461dcc159bd89297443780d635ccc5e3564John Hoford
2635b539461dcc159bd89297443780d635ccc5e3564John Hoford                    // float3 mLight = (float3) {0,-1,0};
2645b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 normal = dv;
2655b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 r = 2 * normal * dot(mLight, normal) - mLight;
2665b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float spec = dot(r, dz);
2675b539461dcc159bd89297443780d635ccc5e3564John Hoford
2685b539461dcc159bd89297443780d635ccc5e3564John Hoford                    // Eye point in this space is in the direction (0,0,-1)
2695b539461dcc159bd89297443780d635ccc5e3564John Hoford                    // Spec * Math.pow(R_z , P) lets use power == 2 (cheap)
2705b539461dcc159bd89297443780d635ccc5e3564John Hoford
271c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford                    float ambient = mat.x * (1/255.f); // ambient
272c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford                    float specular = mat.y * (1/255.f); // specular not used right now
273c81b64d6800dfdb339afe8ad2e89af149ea92fd5John Hoford                    float diffuse = mat.z  * (1/255.f);// diffuse
2745b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float lop = (ambient + diffuse * dot_prod + specular * pow(spec, 10)) * light * opf;
2755b539461dcc159bd89297443780d635ccc5e3564John Hoford                    light -= opf;
2765b539461dcc159bd89297443780d635ccc5e3564John Hoford                    total_color += fcolor * lop;
2775b539461dcc159bd89297443780d635ccc5e3564John Hoford
2785b539461dcc159bd89297443780d635ccc5e3564John Hoford                    zb = zstart + k;
2795b539461dcc159bd89297443780d635ccc5e3564John Hoford                    if (light <= 0) {
2805b539461dcc159bd89297443780d635ccc5e3564John Hoford                        break;
2815b539461dcc159bd89297443780d635ccc5e3564John Hoford                    }
2825b539461dcc159bd89297443780d635ccc5e3564John Hoford                }
2835b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
2845b539461dcc159bd89297443780d635ccc5e3564John Hoford
2855b539461dcc159bd89297443780d635ccc5e3564John Hoford            p += dz;
2865b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
2875b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
2885b539461dcc159bd89297443780d635ccc5e3564John Hoford
2895ee349cd7a75079b6bac1d8ace66455ecd1afb17John Hoford    out = convert_uchar4(clamp(total_color, 0.f, 255.f));
2905b539461dcc159bd89297443780d635ccc5e3564John Hoford    out.a = 0xFF;
2915b539461dcc159bd89297443780d635ccc5e3564John Hoford
2925b539461dcc159bd89297443780d635ccc5e3564John Hoford    return out;
2935b539461dcc159bd89297443780d635ccc5e3564John Hoford}
294