vr.rs revision 5b539461dcc159bd89297443780d635ccc5e3564
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
225b539461dcc159bd89297443780d635ccc5e3564John Hoford#define JITTER_LENGTH 3456
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;
345b539461dcc159bd89297443780d635ccc5e3564John Hoford
355b539461dcc159bd89297443780d635ccc5e3564John Hoford// material color
365b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation opacity;
375b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation color_map;
385b539461dcc159bd89297443780d635ccc5e3564John Hoford
395b539461dcc159bd89297443780d635ccc5e3564John Hofordstatic void fillJitter() {
405b539461dcc159bd89297443780d635ccc5e3564John Hoford    for (int i = 0; i < JITTER_LENGTH; i++) {
415b539461dcc159bd89297443780d635ccc5e3564John Hoford        jitter[i] = rsRand(1.0f);
425b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
435b539461dcc159bd89297443780d635ccc5e3564John Hoford}
445b539461dcc159bd89297443780d635ccc5e3564John Hoford
455b539461dcc159bd89297443780d635ccc5e3564John Hofordvoid setup_vectors() {
465b539461dcc159bd89297443780d635ccc5e3564John Hoford    s = rsMatrixMultiply(&matrix4, (float3) {0.5f, 0.5f, 0.5f}).xyz;
475b539461dcc159bd89297443780d635ccc5e3564John Hoford    dx = rsMatrixMultiply(&matrix3, (float3) {1.f, 0.f, 0.f});
485b539461dcc159bd89297443780d635ccc5e3564John Hoford    dy = rsMatrixMultiply(&matrix3, (float3) {0.f, 1.f, 0.f});
495b539461dcc159bd89297443780d635ccc5e3564John Hoford    dz = rsMatrixMultiply(&matrix3, (float3) {0.f, 0.f, 1.f});
505b539461dcc159bd89297443780d635ccc5e3564John Hoford    zoomFactor = dz.x * dz.x + dz.y * dz.y + dz.z * dz.z;
515b539461dcc159bd89297443780d635ccc5e3564John Hoford    zoomFactor /= dx.x * dx.x + dx.y * dx.y + dx.z * dx.z;
525b539461dcc159bd89297443780d635ccc5e3564John Hoford    base_color.r = 0;
535b539461dcc159bd89297443780d635ccc5e3564John Hoford    base_color.g = 0;
545b539461dcc159bd89297443780d635ccc5e3564John Hoford    base_color.b = 0;
555b539461dcc159bd89297443780d635ccc5e3564John Hoford    base_color.a = 255;
565b539461dcc159bd89297443780d635ccc5e3564John Hoford    fillJitter();
575b539461dcc159bd89297443780d635ccc5e3564John Hoford    float3 mLightRelitvePos = (float3) {0, 0.7071f, -0.7071f}; // light relitve to camera
585b539461dcc159bd89297443780d635ccc5e3564John Hoford    mLight = mLightRelitvePos.x + dx + mLightRelitvePos.y * dy + mLightRelitvePos.z * dz;
595b539461dcc159bd89297443780d635ccc5e3564John Hoford    mLight = normalize(mLight);
605b539461dcc159bd89297443780d635ccc5e3564John Hoford}
615b539461dcc159bd89297443780d635ccc5e3564John Hoford
625b539461dcc159bd89297443780d635ccc5e3564John Hoford// old simple version
635b539461dcc159bd89297443780d635ccc5e3564John Hofordstatic float triLinear_old(short v_0_0_0, short v_0_0_1, short v_0_1_0, short v_0_1_1,
645b539461dcc159bd89297443780d635ccc5e3564John Hoford        short v_1_0_0, short v_1_0_1, short v_1_1_0, short v_1_1_1,
655b539461dcc159bd89297443780d635ccc5e3564John Hoford        float3 delta) {
665b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0_0 = v_0_0_0 + delta.x * (v_0_0_1 - v_0_0_0);
675b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0_1 = v_0_1_0 + delta.x * (v_0_1_1 - v_0_1_0);
685b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1_0 = v_1_0_0 + delta.x * (v_1_0_1 - v_1_0_0);
695b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1_1 = v_1_1_0 + delta.x * (v_1_1_1 - v_1_1_0);
705b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0 = v_0_0 + delta.y * (v_0_1 - v_0_0);
715b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1 = v_1_0 + delta.y * (v_1_1 - v_1_0);
725b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v = v_0 + delta.z * (v_1 - v_0);
735b539461dcc159bd89297443780d635ccc5e3564John Hoford    return v;
745b539461dcc159bd89297443780d635ccc5e3564John Hoford}
755b539461dcc159bd89297443780d635ccc5e3564John Hoford
765b539461dcc159bd89297443780d635ccc5e3564John Hoford//  This seemed to improve over above
775b539461dcc159bd89297443780d635ccc5e3564John Hofordstatic float triLinear(float v_0_0_0, float v_0_0_1, float v_0_1_0, short v_0_1_1,
785b539461dcc159bd89297443780d635ccc5e3564John Hoford        float v_1_0_0, float v_1_0_1, float v_1_1_0, float v_1_1_1,
795b539461dcc159bd89297443780d635ccc5e3564John Hoford        float3 delta) {
805b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0_0 = mix(v_0_0_0, v_0_0_1, delta.x);
815b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0_1 = mix(v_0_1_0, v_0_1_1, delta.x);
825b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1_0 = mix(v_1_0_0, v_1_0_1, delta.x);
835b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1_1 = mix(v_1_1_0, v_1_1_1, delta.x);
845b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_0 = mix(v_0_0, v_0_1, delta.y);
855b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v_1 = mix(v_1_0, v_1_1, delta.y);
865b539461dcc159bd89297443780d635ccc5e3564John Hoford    float v = mix(v_0, v_1, delta.z);
875b539461dcc159bd89297443780d635ccc5e3564John Hoford    return v;
885b539461dcc159bd89297443780d635ccc5e3564John Hoford}
895b539461dcc159bd89297443780d635ccc5e3564John Hoford
905b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation bricks;
915b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation brick_index;
925b539461dcc159bd89297443780d635ccc5e3564John Hofordint brick_dimx;
935b539461dcc159bd89297443780d635ccc5e3564John Hofordint brick_dimy;
945b539461dcc159bd89297443780d635ccc5e3564John Hofordint brick_dimz;
955b539461dcc159bd89297443780d635ccc5e3564John Hoford
965b539461dcc159bd89297443780d635ccc5e3564John Hofordstatic int isInBrick(int3 p) {
975b539461dcc159bd89297443780d635ccc5e3564John Hoford    int bx = p.x >> 5;
985b539461dcc159bd89297443780d635ccc5e3564John Hoford    int by = p.y >> 5;
995b539461dcc159bd89297443780d635ccc5e3564John Hoford    int bz = p.z >> 5;
1005b539461dcc159bd89297443780d635ccc5e3564John Hoford    int brickno = bx + (by + brick_dimy * bz) * brick_dimx;
1015b539461dcc159bd89297443780d635ccc5e3564John Hoford
1025b539461dcc159bd89297443780d635ccc5e3564John Hoford    brickno *= 32 * 32;
1035b539461dcc159bd89297443780d635ccc5e3564John Hoford    int off = brickno + (p.z & 0x1F) * 32 + (p.y & 0x1F);
1045b539461dcc159bd89297443780d635ccc5e3564John Hoford    uint slice = rsGetElementAt_uint(bricks, off);
1055b539461dcc159bd89297443780d635ccc5e3564John Hoford    return slice & (1 << (p.x & 0x1F));
1065b539461dcc159bd89297443780d635ccc5e3564John Hoford}
1075b539461dcc159bd89297443780d635ccc5e3564John Hoford
1085b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation volume;
1095b539461dcc159bd89297443780d635ccc5e3564John Hofordrs_allocation zbuff;
1105b539461dcc159bd89297443780d635ccc5e3564John Hofordbool debug = true;
1115b539461dcc159bd89297443780d635ccc5e3564John Hoford
1125b539461dcc159bd89297443780d635ccc5e3564John Hoforduchar4 __attribute__ ((kernel)) draw_z_buffer(float2 in, uint32_t x, uint32_t y) {
1135b539461dcc159bd89297443780d635ccc5e3564John Hoford    uchar4 out = base_color;
1145b539461dcc159bd89297443780d635ccc5e3564John Hoford
1155b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zsuface = in.x + .5f;
1165b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zstart = zsuface;
1175b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zend = in.y - 2.f;//0.5f;
1185b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zlen = zend - zstart;
1195b539461dcc159bd89297443780d635ccc5e3564John Hoford    float step_dist = length(dz);
1205b539461dcc159bd89297443780d635ccc5e3564John Hoford
1215b539461dcc159bd89297443780d635ccc5e3564John Hoford    if (zstart == FLOAT_MAX || zlen < 0) {
1225b539461dcc159bd89297443780d635ccc5e3564John Hoford        return out;
1235b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
1245b539461dcc159bd89297443780d635ccc5e3564John Hoford
1255b539461dcc159bd89297443780d635ccc5e3564John Hoford    float3 p = s + x * dx + y * dy + dz * zstart;
1265b539461dcc159bd89297443780d635ccc5e3564John Hoford    float zb = zend;
1275b539461dcc159bd89297443780d635ccc5e3564John Hoford    int izlen = (int) zlen;
1285b539461dcc159bd89297443780d635ccc5e3564John Hoford    float light = 1;
1295b539461dcc159bd89297443780d635ccc5e3564John Hoford    float4 total_color = (float4) {0.f, 0.f, 0.f, 0.f};
1305b539461dcc159bd89297443780d635ccc5e3564John Hoford
1315b539461dcc159bd89297443780d635ccc5e3564John Hoford    if (false) { // show the walls only used for debuging
1325b539461dcc159bd89297443780d635ccc5e3564John Hoford        int3 ip = convert_int3(p);
1335b539461dcc159bd89297443780d635ccc5e3564John Hoford        ip = clamp(ip, 4, 500);
1345b539461dcc159bd89297443780d635ccc5e3564John Hoford        short pix = rsGetElementAt_short(volume, ip.x, ip.y, ip.z);
1355b539461dcc159bd89297443780d635ccc5e3564John Hoford
1365b539461dcc159bd89297443780d635ccc5e3564John Hoford        int intensity = (((short) pix) & 0xFFFF);
1375b539461dcc159bd89297443780d635ccc5e3564John Hoford        //   intensity = clamp(intensity,0,400);
1385b539461dcc159bd89297443780d635ccc5e3564John Hoford        uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
1395b539461dcc159bd89297443780d635ccc5e3564John Hoford        int op = rsGetElementAt_uchar(opacity, intensity);
1405b539461dcc159bd89297443780d635ccc5e3564John Hoford
1415b539461dcc159bd89297443780d635ccc5e3564John Hoford        out.r = color.r;
1425b539461dcc159bd89297443780d635ccc5e3564John Hoford        out.g = color.g;
1435b539461dcc159bd89297443780d635ccc5e3564John Hoford        out.b = color.b;
1445b539461dcc159bd89297443780d635ccc5e3564John Hoford        out.a = 255;
1455b539461dcc159bd89297443780d635ccc5e3564John Hoford        return out;
1465b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
1475b539461dcc159bd89297443780d635ccc5e3564John Hoford    {
1485b539461dcc159bd89297443780d635ccc5e3564John Hoford        int3 ip = convert_int3(p);
1495b539461dcc159bd89297443780d635ccc5e3564John Hoford
1505b539461dcc159bd89297443780d635ccc5e3564John Hoford        if (isInBrick(ip)) { // isInBrick(ip)) {
1515b539461dcc159bd89297443780d635ccc5e3564John Hoford
1525b539461dcc159bd89297443780d635ccc5e3564John Hoford            float3 delta = p - convert_float3(ip);
1535b539461dcc159bd89297443780d635ccc5e3564John Hoford            // TODO switch to rsAllocationVLoadX_short2
1545b539461dcc159bd89297443780d635ccc5e3564John Hoford            // short2 tmps = rsAllocationVLoadX_short2(volume, ip.x + 0, ip.y + 0, ip.z + 0);
1555b539461dcc159bd89297443780d635ccc5e3564John Hoford            //  float2 tmp =   convert_float2(tmps);
1565b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_0_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 0);
1575b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_0_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 0);
1585b539461dcc159bd89297443780d635ccc5e3564John Hoford
1595b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_0_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
1605b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_0_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
1615b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_1_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 1);
1625b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_1_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 1);
1635b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_1_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
1645b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v_1_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
1655b539461dcc159bd89297443780d635ccc5e3564John Hoford            float v = triLinear(v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
1665b539461dcc159bd89297443780d635ccc5e3564John Hoford                    v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
1675b539461dcc159bd89297443780d635ccc5e3564John Hoford                    delta);
1685b539461dcc159bd89297443780d635ccc5e3564John Hoford            int intensity = (((short) v) & 0xFFFF);
1695b539461dcc159bd89297443780d635ccc5e3564John Hoford            uchar op = rsGetElementAt_uchar(opacity, intensity);
1705b539461dcc159bd89297443780d635ccc5e3564John Hoford
1715b539461dcc159bd89297443780d635ccc5e3564John Hoford            if (op != 0) { // near the surface "broken"
1725b539461dcc159bd89297443780d635ccc5e3564John Hoford
1735b539461dcc159bd89297443780d635ccc5e3564John Hoford                float sdx = rsGetElementAt_float2(zbuff, max(0, (int) x - 1), y).x - in.x;
1745b539461dcc159bd89297443780d635ccc5e3564John Hoford                float sdy = rsGetElementAt_float2(zbuff, x, max(0, (int) y - 1)).x - in.x;
1755b539461dcc159bd89297443780d635ccc5e3564John Hoford                float dot_prod = sqrt(1 / (1 + (sdy * sdy + sdx * sdx) * zoomFactor));
1765b539461dcc159bd89297443780d635ccc5e3564John Hoford                float opf = op / 255.f;
1775b539461dcc159bd89297443780d635ccc5e3564John Hoford                uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
1785b539461dcc159bd89297443780d635ccc5e3564John Hoford                uchar4 mat = rsGetElementAt_uchar4(color_map, intensity * 2 + 1);
1795b539461dcc159bd89297443780d635ccc5e3564John Hoford                float4 fcolor = convert_float4(color);;
1805b539461dcc159bd89297443780d635ccc5e3564John Hoford
1815b539461dcc159bd89297443780d635ccc5e3564John Hoford                float ambient = mat.x / 255.f;
1825b539461dcc159bd89297443780d635ccc5e3564John Hoford                float specular = mat.y / 255.f;
1835b539461dcc159bd89297443780d635ccc5e3564John Hoford                float diffuse = mat.z / 255.f;
1845b539461dcc159bd89297443780d635ccc5e3564John Hoford                float lop = (ambient + diffuse * dot_prod) * light * opf;
1855b539461dcc159bd89297443780d635ccc5e3564John Hoford                light -= opf;
1865b539461dcc159bd89297443780d635ccc5e3564John Hoford                total_color += fcolor * lop;
1875b539461dcc159bd89297443780d635ccc5e3564John Hoford                zb = zstart;
1885b539461dcc159bd89297443780d635ccc5e3564John Hoford
1895b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
1905b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
1915b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
1925b539461dcc159bd89297443780d635ccc5e3564John Hoford    p += dz * rsRand(2.f);
1935b539461dcc159bd89297443780d635ccc5e3564John Hoford
1945b539461dcc159bd89297443780d635ccc5e3564John Hoford    if (light > 0) {
1955b539461dcc159bd89297443780d635ccc5e3564John Hoford        for (int k = 0; k < izlen - 1; k++) {
1965b539461dcc159bd89297443780d635ccc5e3564John Hoford
1975b539461dcc159bd89297443780d635ccc5e3564John Hoford            int3 ip = convert_int3(p);
1985b539461dcc159bd89297443780d635ccc5e3564John Hoford            if (isInBrick(ip)) {
1995b539461dcc159bd89297443780d635ccc5e3564John Hoford                float3 delta = p - convert_float3(ip);
2005b539461dcc159bd89297443780d635ccc5e3564John Hoford
2015b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_0_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 0);
2025b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_0_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 0);
2035b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_0_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
2045b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_0_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
2055b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_1_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 1);
2065b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_1_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 1);
2075b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_1_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
2085b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v_1_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
2095b539461dcc159bd89297443780d635ccc5e3564John Hoford                float v = triLinear(v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
2105b539461dcc159bd89297443780d635ccc5e3564John Hoford                        v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
2115b539461dcc159bd89297443780d635ccc5e3564John Hoford                        delta);
2125b539461dcc159bd89297443780d635ccc5e3564John Hoford                int intensity = (((short) v) & 0xFFFF);
2135b539461dcc159bd89297443780d635ccc5e3564John Hoford                uchar op = rsGetElementAt_uchar(opacity, intensity);
2145b539461dcc159bd89297443780d635ccc5e3564John Hoford
2155b539461dcc159bd89297443780d635ccc5e3564John Hoford                if (op != 0) {
2165b539461dcc159bd89297443780d635ccc5e3564John Hoford
2175b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 v;
2185b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 vn;
2195b539461dcc159bd89297443780d635ccc5e3564John Hoford
2205b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_0_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 0, ip.z + 0);
2215b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_1_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 1, ip.z + 0);
2225b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_0_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 0, ip.z + 1);
2235b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_1_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 1, ip.z + 1);
2245b539461dcc159bd89297443780d635ccc5e3564John Hoford                    v.x = triLinear(v_0_0_1, v_0_0_2, v_0_1_1, v_0_1_2,
2255b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_1_0_1, v_1_0_2, v_1_1_1, v_1_1_2,
2265b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2275b539461dcc159bd89297443780d635ccc5e3564John Hoford
2285b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_0_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 0, ip.z + 0);
2295b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_1_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 1, ip.z + 0);
2305b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_0_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 0, ip.z + 1);
2315b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_1_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 1, ip.z + 1);
2325b539461dcc159bd89297443780d635ccc5e3564John Hoford                    vn.x = triLinear(v_0_0_n, v_0_0_0, v_0_1_n, v_0_1_0,
2335b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_1_0_n, v_1_0_0, v_1_1_n, v_1_1_0,
2345b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2355b539461dcc159bd89297443780d635ccc5e3564John Hoford
2365b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_2_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 2, ip.z + 0);
2375b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_2_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 2, ip.z + 0);
2385b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_2_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 2, ip.z + 1);
2395b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_2_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 2, ip.z + 1);
2405b539461dcc159bd89297443780d635ccc5e3564John Hoford                    v.y = triLinear(v_0_1_0, v_0_1_1, v_0_2_0, v_0_2_1,
2415b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_1_1_0, v_1_1_1, v_1_2_0, v_1_2_1,
2425b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2435b539461dcc159bd89297443780d635ccc5e3564John Hoford
2445b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_n_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0);
2455b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_0_n_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0);
2465b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_n_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1);
2475b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_1_n_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1);
2485b539461dcc159bd89297443780d635ccc5e3564John Hoford                    vn.y = triLinear(v_0_n_0, v_0_n_1, v_0_0_0, v_0_0_1,
2495b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_1_n_0, v_1_n_1, v_1_0_0, v_1_0_1,
2505b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2515b539461dcc159bd89297443780d635ccc5e3564John Hoford
2525b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_n_0_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z - 1);
2535b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_n_0_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z - 1);
2545b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_n_1_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z - 1);
2555b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_n_1_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z - 1);
2565b539461dcc159bd89297443780d635ccc5e3564John Hoford                    vn.z = triLinear(v_n_0_0, v_n_0_1, v_n_1_0, v_n_1_1,
2575b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1,
2585b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2595b539461dcc159bd89297443780d635ccc5e3564John Hoford
2605b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_2_0_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 2);
2615b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_2_0_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 2);
2625b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_2_1_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 2);
2635b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float v_2_1_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 2);
2645b539461dcc159bd89297443780d635ccc5e3564John Hoford                    v.z = triLinear(v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1,
2655b539461dcc159bd89297443780d635ccc5e3564John Hoford                            v_2_0_0, v_2_0_1, v_2_1_0, v_2_1_1,
2665b539461dcc159bd89297443780d635ccc5e3564John Hoford                            delta);
2675b539461dcc159bd89297443780d635ccc5e3564John Hoford
2685b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 dv = normalize(v - vn);
2695b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float dot_prod = dot(dv, dz);
2705b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float opf = op / 255.f;
2715b539461dcc159bd89297443780d635ccc5e3564John Hoford
2725b539461dcc159bd89297443780d635ccc5e3564John Hoford                    uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2);
2735b539461dcc159bd89297443780d635ccc5e3564John Hoford                    uchar4 mat = rsGetElementAt_uchar4(color_map, intensity * 2 + 1);
2745b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float4 fcolor = convert_float4(color);;
2755b539461dcc159bd89297443780d635ccc5e3564John Hoford
2765b539461dcc159bd89297443780d635ccc5e3564John Hoford                    // float3 mLight = (float3) {0,-1,0};
2775b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 normal = dv;
2785b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float3 r = 2 * normal * dot(mLight, normal) - mLight;
2795b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float spec = dot(r, dz);
2805b539461dcc159bd89297443780d635ccc5e3564John Hoford
2815b539461dcc159bd89297443780d635ccc5e3564John Hoford                    // Eye point in this space is in the direction (0,0,-1)
2825b539461dcc159bd89297443780d635ccc5e3564John Hoford                    // Spec * Math.pow(R_z , P) lets use power == 2 (cheap)
2835b539461dcc159bd89297443780d635ccc5e3564John Hoford
2845b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float ambient = mat.x / 255.f; // ambient
2855b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float specular = mat.y / 255.f; // specular not used right now
2865b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float diffuse = mat.z / 255.f; // diffuse
2875b539461dcc159bd89297443780d635ccc5e3564John Hoford                    float lop = (ambient + diffuse * dot_prod + specular * pow(spec, 10)) * light * opf;
2885b539461dcc159bd89297443780d635ccc5e3564John Hoford                    light -= opf;
2895b539461dcc159bd89297443780d635ccc5e3564John Hoford                    total_color += fcolor * lop;
2905b539461dcc159bd89297443780d635ccc5e3564John Hoford
2915b539461dcc159bd89297443780d635ccc5e3564John Hoford                    zb = zstart + k;
2925b539461dcc159bd89297443780d635ccc5e3564John Hoford                    if (light <= 0) {
2935b539461dcc159bd89297443780d635ccc5e3564John Hoford                        break;
2945b539461dcc159bd89297443780d635ccc5e3564John Hoford                    }
2955b539461dcc159bd89297443780d635ccc5e3564John Hoford                }
2965b539461dcc159bd89297443780d635ccc5e3564John Hoford            }
2975b539461dcc159bd89297443780d635ccc5e3564John Hoford
2985b539461dcc159bd89297443780d635ccc5e3564John Hoford            p += dz;
2995b539461dcc159bd89297443780d635ccc5e3564John Hoford        }
3005b539461dcc159bd89297443780d635ccc5e3564John Hoford    }
3015b539461dcc159bd89297443780d635ccc5e3564John Hoford
3025b539461dcc159bd89297443780d635ccc5e3564John Hoford    out = convert_uchar4(total_color);
3035b539461dcc159bd89297443780d635ccc5e3564John Hoford    out.a = 0xFF;
3045b539461dcc159bd89297443780d635ccc5e3564John Hoford
3055b539461dcc159bd89297443780d635ccc5e3564John Hoford    return out;
3065b539461dcc159bd89297443780d635ccc5e3564John Hoford}
307