1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#pragma version(1) 18#pragma rs java_package_name(com.example.android.rs.vr.engine) 19#pragma rs_fp_relaxed 20 21#define FLOAT_MAX 3.4028234E30f 22#define JITTER_LENGTH 3457 23float jitter[JITTER_LENGTH]; 24 25float3 s; 26float3 dx; 27float3 dy; 28float3 dz; 29float zoomFactor; 30rs_matrix4x4 matrix4; 31rs_matrix3x3 matrix3; 32uchar4 base_color; 33static float3 mLight; 34static float rscale; 35 36// material color 37rs_allocation opacity; 38rs_allocation color_map; 39 40static void fillJitter() { 41 for (int i = 0; i < JITTER_LENGTH; i++) { 42 jitter[i] = (rsRand(rscale)+rsRand(rscale)+rsRand(rscale))/3; 43 } 44} 45 46void setup_vectors() { 47 s = rsMatrixMultiply(&matrix4, (float3) {0.5f, 0.5f, 0.5f}).xyz; 48 dx = rsMatrixMultiply(&matrix3, (float3) {1.f, 0.f, 0.f}); 49 dy = rsMatrixMultiply(&matrix3, (float3) {0.f, 1.f, 0.f}); 50 dz = rsMatrixMultiply(&matrix3, (float3) {0.f, 0.f, 1.f}); 51 zoomFactor = dz.x * dz.x + dz.y * dz.y + dz.z * dz.z; 52 zoomFactor /= dx.x * dx.x + dx.y * dx.y + dx.z * dx.z; 53 base_color.r = 0; 54 base_color.g = 0; 55 base_color.b = 0; 56 base_color.a = 255; 57 58 float3 mLightRelitvePos = (float3) {0.f, 0.7071f, -0.7071f}; // light relitve to camera 59 mLight = mLightRelitvePos.x + dx + mLightRelitvePos.y * dy + mLightRelitvePos.z * dz; 60 mLight = normalize(mLight); 61 rscale = 1.5f/length(dz); 62 fillJitter(); 63} 64 65static float triLinear(float v_0_0_0, float v_0_0_1, float v_0_1_0, float v_0_1_1, 66 float v_1_0_0, float v_1_0_1, float v_1_1_0, float v_1_1_1, 67 float3 delta) { 68 float v_0_0 = mix(v_0_0_0, v_0_0_1, delta.x); 69 float v_0_1 = mix(v_0_1_0, v_0_1_1, delta.x); 70 float v_1_0 = mix(v_1_0_0, v_1_0_1, delta.x); 71 float v_1_1 = mix(v_1_1_0, v_1_1_1, delta.x); 72 float v_0 = mix(v_0_0, v_0_1, delta.y); 73 float v_1 = mix(v_1_0, v_1_1, delta.y); 74 float v = mix(v_0, v_1, delta.z); 75 return v; 76} 77 78rs_allocation bricks; 79rs_allocation brick_index; 80int brick_dimx; 81int brick_dimy; 82int brick_dimz; 83 84static int isInBrick(int3 p) { 85 int bx = p.x >> 5; 86 int by = p.y >> 5; 87 int bz = p.z >> 5; 88 int brickno = bx + (by + brick_dimy * bz) * brick_dimx; 89 90 brickno *= 32 * 32; 91 int off = brickno + (p.z & 0x1F) * 32 + (p.y & 0x1F); 92 uint slice = rsGetElementAt_uint(bricks, off); 93 return slice & (1 << (p.x & 0x1F)); 94} 95 96rs_allocation volume; 97rs_allocation zbuff; 98bool debug = true; 99 100uchar4 __attribute__ ((kernel)) draw_z_buffer(float2 in, uint32_t x, uint32_t y) { 101 uchar4 out = base_color; 102 103 float zsuface = in.x + .5f; 104 float zstart = zsuface; 105 float zend = in.y - 2.f;//0.5f; 106 float zlen = zend - zstart; 107 108 if (zstart == FLOAT_MAX || zlen < 0) { 109 return out; 110 } 111 112 float3 p = s + x * dx + y * dy + dz * zstart; 113 float zb = zend; 114 int izlen = (int) zlen; 115 float light = 1; 116 float4 total_color = (float4) {0.f, 0.f, 0.f, 0.f}; 117 118 if (false) { // show the walls only used for debuging 119 int3 ip = convert_int3(p); 120 ip = clamp(ip, 4, 500); 121 short pix = rsGetElementAt_short(volume, ip.x, ip.y, ip.z); 122 123 int intensity = (((short) pix) & 0xFFFF); 124 // intensity = clamp(intensity,0,400); 125 uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2); 126 // int op = rsGetElementAt_uchar(opacity, intensity); 127 128 out.r = color.r; 129 out.g = color.g; 130 out.b = color.b; 131 out.a = 255; 132 return out; 133 } 134 { 135 int3 ip = convert_int3(p); 136 137 if (isInBrick(ip)) { // isInBrick(ip)) { 138 139 float3 delta = p - convert_float3(ip); 140 // TODO switch to rsAllocationVLoadX_short2 141 // short2 tmps = rsAllocationVLoadX_short2(volume, ip.x + 0, ip.y + 0, ip.z + 0); 142 // float2 tmp = convert_float2(tmps); 143 float v_0_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 0); 144 float v_0_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 0); 145 146 float v_0_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0); 147 float v_0_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0); 148 float v_1_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 1); 149 float v_1_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 1); 150 float v_1_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1); 151 float v_1_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1); 152 float v = triLinear(v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1, 153 v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1, 154 delta); 155 int intensity = (((short) v) & 0xFFFF); 156 uchar op = rsGetElementAt_uchar(opacity, intensity); 157 158 if (op != 0) { // near the surface "broken" 159 160 float sdx = rsGetElementAt_float2(zbuff, max(0, (int) x - 1), y).x - in.x; 161 float sdy = rsGetElementAt_float2(zbuff, x, max(0, (int) y - 1)).x - in.x; 162 float dot_prod = sqrt(1 / (1 + (sdy * sdy + sdx * sdx) * zoomFactor)); 163 float opf = op * (1/255.f); 164 uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2); 165 uchar4 mat = rsGetElementAt_uchar4(color_map, intensity * 2 + 1); 166 float4 fcolor = convert_float4(color);; 167 168 float ambient = mat.x * (1/255.f); 169 // float specular = mat.y * (1/255.f); 170 float diffuse = mat.z * (1/255.f); 171 float lop = (ambient + diffuse * dot_prod) * light * opf; 172 light -= opf; 173 total_color += fcolor * lop; 174 zb = zstart; 175 176 } 177 } 178 } 179 p += dz * jitter[(x+(y<<11))%JITTER_LENGTH]; 180 181 if (light > 0) { 182 for (int k = 0; k < izlen - 1; k++) { 183 184 int3 ip = convert_int3(p); 185 if (isInBrick(ip)) { 186 float3 delta = p - convert_float3(ip); 187 188 float v_0_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 0); 189 float v_0_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 0); 190 float v_0_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0); 191 float v_0_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0); 192 float v_1_0_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 1); 193 float v_1_0_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 1); 194 float v_1_1_0 = (float) rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1); 195 float v_1_1_1 = (float) rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1); 196 float v = triLinear(v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1, 197 v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1, 198 delta); 199 int intensity = (((short) v) & 0xFFFF); 200 uchar op = rsGetElementAt_uchar(opacity, intensity); 201 202 if (op != 0) { 203 204 float3 v; 205 float3 vn; 206 207 float v_0_0_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 0, ip.z + 0); 208 float v_0_1_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 1, ip.z + 0); 209 float v_1_0_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 0, ip.z + 1); 210 float v_1_1_2 = rsGetElementAt_short(volume, ip.x + 2, ip.y + 1, ip.z + 1); 211 v.x = triLinear(v_0_0_1, v_0_0_2, v_0_1_1, v_0_1_2, 212 v_1_0_1, v_1_0_2, v_1_1_1, v_1_1_2, 213 delta); 214 215 float v_0_0_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 0, ip.z + 0); 216 float v_0_1_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 1, ip.z + 0); 217 float v_1_0_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 0, ip.z + 1); 218 float v_1_1_n = rsGetElementAt_short(volume, ip.x - 1, ip.y + 1, ip.z + 1); 219 vn.x = triLinear(v_0_0_n, v_0_0_0, v_0_1_n, v_0_1_0, 220 v_1_0_n, v_1_0_0, v_1_1_n, v_1_1_0, 221 delta); 222 223 float v_0_2_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 2, ip.z + 0); 224 float v_0_2_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 2, ip.z + 0); 225 float v_1_2_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 2, ip.z + 1); 226 float v_1_2_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 2, ip.z + 1); 227 v.y = triLinear(v_0_1_0, v_0_1_1, v_0_2_0, v_0_2_1, 228 v_1_1_0, v_1_1_1, v_1_2_0, v_1_2_1, 229 delta); 230 231 float v_0_n_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 0); 232 float v_0_n_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 0); 233 float v_1_n_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 1); 234 float v_1_n_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 1); 235 vn.y = triLinear(v_0_n_0, v_0_n_1, v_0_0_0, v_0_0_1, 236 v_1_n_0, v_1_n_1, v_1_0_0, v_1_0_1, 237 delta); 238 239 float v_n_0_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z - 1); 240 float v_n_0_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z - 1); 241 float v_n_1_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z - 1); 242 float v_n_1_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z - 1); 243 vn.z = triLinear(v_n_0_0, v_n_0_1, v_n_1_0, v_n_1_1, 244 v_0_0_0, v_0_0_1, v_0_1_0, v_0_1_1, 245 delta); 246 247 float v_2_0_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 0, ip.z + 2); 248 float v_2_0_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 0, ip.z + 2); 249 float v_2_1_0 = rsGetElementAt_short(volume, ip.x + 0, ip.y + 1, ip.z + 2); 250 float v_2_1_1 = rsGetElementAt_short(volume, ip.x + 1, ip.y + 1, ip.z + 2); 251 v.z = triLinear(v_1_0_0, v_1_0_1, v_1_1_0, v_1_1_1, 252 v_2_0_0, v_2_0_1, v_2_1_0, v_2_1_1, 253 delta); 254 255 float3 dv = normalize(v - vn); 256 float dot_prod = dot(dv, dz); 257 float opf = op / 255.f; 258 259 uchar4 color = rsGetElementAt_uchar4(color_map, intensity * 2); 260 uchar4 mat = rsGetElementAt_uchar4(color_map, intensity * 2 + 1); 261 float4 fcolor = convert_float4(color);; 262 263 // float3 mLight = (float3) {0,-1,0}; 264 float3 normal = dv; 265 float3 r = 2 * normal * dot(mLight, normal) - mLight; 266 float spec = dot(r, dz); 267 268 // Eye point in this space is in the direction (0,0,-1) 269 // Spec * Math.pow(R_z , P) lets use power == 2 (cheap) 270 271 float ambient = mat.x * (1/255.f); // ambient 272 float specular = mat.y * (1/255.f); // specular not used right now 273 float diffuse = mat.z * (1/255.f);// diffuse 274 float lop = (ambient + diffuse * dot_prod + specular * pow(spec, 10)) * light * opf; 275 light -= opf; 276 total_color += fcolor * lop; 277 278 zb = zstart + k; 279 if (light <= 0) { 280 break; 281 } 282 } 283 } 284 285 p += dz; 286 } 287 } 288 289 out = convert_uchar4(clamp(total_color, 0.f, 255.f)); 290 out.a = 0xFF; 291 292 return out; 293} 294