float inner_tesslevel() { vec4 bbox_min = texelFetch(attribute_texture, int(vIndex[ID]) * 5 + 2); vec4 bbox_max = texelFetch(attribute_texture, int(vIndex[ID]) * 5 + 3); vec3 combin[8]; int i, j; float max_length = 0.0; combin[0] = to_screen_space(vec3(bbox_min.x, bbox_min.y, bbox_min.z)).xyz; combin[1] = to_screen_space(vec3(bbox_min.x, bbox_min.y, bbox_max.z)).xyz; combin[2] = to_screen_space(vec3(bbox_min.x, bbox_max.y, bbox_min.z)).xyz; combin[3] = to_screen_space(vec3(bbox_min.x, bbox_max.y, bbox_max.z)).xyz; combin[4] = to_screen_space(vec3(bbox_max.x, bbox_min.y, bbox_min.z)).xyz; combin[5] = to_screen_space(vec3(bbox_max.x, bbox_min.y, bbox_max.z)).xyz; combin[6] = to_screen_space(vec3(bbox_max.x, bbox_max.y, bbox_min.z)).xyz; combin[7] = to_screen_space(vec3(bbox_max.x, bbox_max.y, bbox_max.z)).xyz; for ( i = 0; i < 7; i++ ) { for ( j = i + 1; j < 8; j++ ) { float temp_length = length(combin[i].xy - combin[j].xy); if ( temp_length > max_length ) { max_length = temp_length; } } } max_length = clamp(max_length, 0, 900); return clamp(ceil(max_length / 8.0), 2.0, 64.0); }
vec4 gradient_color(int stop_start, int stop_end, float t) { vec4 color = texelFetch(instance_data, ivec2(instance_offset.x + stop_start, instance_offset.y), 0); float last_stop_pos = texelFetch(instance_data, ivec2(instance_offset.x + stop_start + 1, instance_offset.y), 0).x; for (int i = stop_start; i < stop_end; i+=2) { vec4 stop_color = texelFetch(instance_data, ivec2(instance_offset.x + i, instance_offset.y), 0); float stop_pos = texelFetch(instance_data, ivec2(instance_offset.x + i + 1, instance_offset.y), 0).x; float tt = clamp((t - last_stop_pos)/(stop_pos - last_stop_pos), 0.0, 1.0); color = mix(color, stop_color, tt); last_stop_pos = stop_pos; } return color; }
int GetVoxel(vec3 voxel) { ivec3 arrayIndex; if(GetArrayIndex(voxel, arrayIndex)) { return int(floor(texelFetch(data, arrayIndex, 0).g * 255)); } return 255; // Return vacuum if block is invalid }
vec4 control_polygon_length(in samplerBuffer data, in int offset, in int u, in int v) { int i, j; vec4 output = vec4(0.0); vec4 first, second; mat4 mvp = projection_matrix * view_matrix * model_matrix; // 2------3 // | | // | | // 0------1 /*For Edge 01*/ for ( i = 1; i < u; ++i ) { output[0] += edge_length(texelFetch(data, offset + i).xyz, texelFetch(data, offset + i - 1).xyz); } /*For Edge 13*/ for ( i = 2 * u - 1; i < u * v; i += u ) { output[1] += edge_length(texelFetch(data, offset + i).xyz, texelFetch(data, offset + i - u).xyz); } /*For Edge 23*/ for ( i = u * v - u + 1; i < u * v; ++i ) { output[2] += edge_length(texelFetch(data, offset + i).xyz, texelFetch(data, offset + i - 1).xyz); } /*For Edge 02*/ for ( i = u; i <= u * v - u; i += u ) { output[3] += edge_length(texelFetch(data, offset + i).xyz, texelFetch(data, offset + i - u).xyz); } /**/ return output; }
i32 main() { SDL_Window * sdl_window; SDL_GLContext sdl_glcontext; gfWindow(&sdl_window, &sdl_glcontext, 0, 0, "App", 1280, 720, 4); gpu_storage_t mesh = {0}; mesh.format = xyz_f32; mesh.count = 3; mesh = gfStorageCreateFromStruct(mesh); mesh.as_vec3[0].x = -0.5f; mesh.as_vec3[0].y = -0.5f; mesh.as_vec3[0].z = 0.0f; mesh.as_vec3[1].x = 0.0f; mesh.as_vec3[1].y = 0.5f; mesh.as_vec3[1].z = 0.0f; mesh.as_vec3[2].x = 0.5f; mesh.as_vec3[2].y = -0.5f; mesh.as_vec3[2].z = 0.0f; gpu_cmd_t cmd[1] = {0}; cmd[0].count = mesh.count; cmd[0].instance_count = 1; const char * vs_str = VERT_HEAD STR ( layout(binding = 0) uniform samplerBuffer in_pos; void main() { vec3 pos = texelFetch(in_pos, gl_VertexID).xyz; gl_Position = vec4(pos, 1.f); }
void main() { #ifdef MULTISAMPLE ivec2 screensize =textureSize( g_depth /*,0*/ ); #else ivec2 screensize =textureSize( g_depth, 0 ); #endif ndc_position = ( gl_FragCoord.xy / screensize ) * vec2(1) - vec2(1); // Retrieve data from gbuffer #ifndef MULTISAMPLE //vec3 f_position = vec3(vec4(positionFromDepth( 0 ),1)); vec4 fragCoord =texture( g_position, ndc_position).rgba; vec3 f_normal = mat3(mat_view)*texture(g_normal, ndc_position).rgb; vec3 f_diffuse = texture(g_diffusespec, ndc_position).rgb; float f_specular = texture(g_diffusespec, ndc_position).a; #endif vec3 color =vec3(0); #ifdef MULTISAMPLE /* For MS, we average over all the samples */ for( int i=0; i < NUM_SAMPLES; i++ ) { vec4 fragCoord =texelFetch( g_position, ivec2(gl_FragCoord.xy), i).rgba; vec3 f_normal = mat3(mat_view) * texelFetch( g_normal, ivec2(gl_FragCoord.xy), i).rgb; vec3 f_diffuse = texelFetch( g_diffusespec, ivec2(gl_FragCoord.xy), i).rgb; float f_specular = texelFetch( g_diffusespec, ivec2(gl_FragCoord.xy), i).a; #endif /* Calculate the NDC from the stored fragCoord, then reconstruct the view-space position using the inverse projection matrix */ vec4 ndcPos; ndcPos.xy = ((2.0 * fragCoord.xy) - (2.0 * vec2(0))) / (screensize) - 1; ndcPos.z = (2.0 * fragCoord.z - gl_DepthRange.near - gl_DepthRange.far) / (gl_DepthRange.far - gl_DepthRange.near); ndcPos.w = 1.0; vec4 clipPos = ndcPos / fragCoord.w; vec3 f_position = vec3(mat_windowtoview * clipPos); float attenuation = 1.0; vec3 diffuse; vec3 specular; vec3 lighting = f_diffuse * 0.001; // hard-coded ambient component vec3 viewDir = normalize( - f_position); if( light_direction.xyz == vec3(0) ) { // assumes point-light // Diffuse vec3 lightDir = normalize(light_position - f_position); diffuse = max(dot(f_normal, lightDir), 0.0) * f_diffuse * light_intensity; // Specular vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(f_normal, halfwayDir), 0.0), 16.0); specular = light_intensity * spec * f_specular; // Attenuation float distance = length(light_position - f_position); attenuation = 1.0 / ( light_attenuation.x + // constant light_attenuation.y * distance + // linear light_attenuation.z * distance * distance); // quadratic } else { // directional light lighting = f_diffuse * 0.1; // DELETE ME vec3 lightDir = normalize(-light_direction); float diff = max(dot(f_normal, lightDir), 0.0); diffuse = light_intensity * diff * f_diffuse; // Specular vec3 reflectDir = reflect(-lightDir, f_normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 16.0 ); specular = light_intensity * spec * f_specular; } diffuse *= attenuation; specular *= attenuation; lighting += diffuse + specular; #ifdef MULTISAMPLE color += (1.0 / NUM_SAMPLES) * lighting; } #else color =lighting; #endif fragColor = vec4(color, 1.0); }
void main() { //Calculate the ray direction using viewport information vec3 rayDirection = frag_worldpos - RayOrigin; rayDirection = normalize(rayDirection); //Cube ray intersection test vec3 invR = 1.0 / rayDirection; vec3 tbot = invR * (volumeMin - RayOrigin); vec3 ttop = invR * (volumeMax - RayOrigin); //Now sort all elements of tbot and ttop to find the two min and max elements vec3 tmin = min(ttop, tbot); //Closest planes vec2 t = max(tmin.xx, tmin.yz); //Out of the closest planes, find the last to be entered (collision point) float tnear = max(t.x, t.y);//... //If the viewpoint is penetrating the volume, make sure to only cast the ray //from the eye position, not behind it tnear = max(0.0, tnear); //Now work out when the ray will leave the volume vec3 tmax = max(ttop, tbot); //Distant planes t = min(tmax.xx, tmax.yz);//Find the first plane to be exited float tfar = min(t.x, t.y);//... //Check what the screen depth is to make sure we don't sample the //volume past any standard GL objects float bufferDepth = texelFetch(DepthTexture, ivec2(gl_FragCoord.xy), 0).r; float depth = recalcZCoord(bufferDepth); tfar = min(depth, tfar); //We need to calculate the ray's starting position. We add a random //fraction of the stepsize to the original starting point to dither //the output float starting_offset = tnear; if (DitherRay != 0) starting_offset += StepSize * fract(sin(gl_FragCoord.x * 12.9898 + gl_FragCoord.y * 78.233) * 43758.5453); vec3 rayPos = RayOrigin + rayDirection * starting_offset; //The color accumulation variable vec4 color = vec4(0.0, 0.0, 0.0, 0.0); //Start the sampling by initialising the ray variables. We take the //first sample ready to integrate to the next sample vec4 first_sample = texture(DataTexture, (rayPos + 1.0) * 0.5); float lastsamplea = first_sample.a; vec4 lastTransfer = texture(IntTransferTexture, lastsamplea); vec3 lastnorm = first_sample.xyz * 2.0 - vec3(1.0); float lastnorm_length = length(lastnorm); lastnorm = (lastnorm_length == 0) ? -rayDirection : lastnorm / lastnorm_length; //Make this into the ray position step vector rayDirection *= StepSize; rayPos += rayDirection; for (float length = tfar - tnear; length > 0.0; length -= StepSize, rayPos += rayDirection) { //Grab the volume sample vec4 sample = texture(DataTexture, (rayPos - volumeMin) * invVolumeDimensions); float delta = sample.a - lastsamplea; vec4 transfer = texture(IntTransferTexture, sample.a); float deltaT = transfer.a - lastTransfer.a; vec3 deltaK = transfer.rgb - lastTransfer.rgb; vec4 src; if (delta == 0.0) { //Special case where the integration breaks down, just use the constant val. src = texture(TransferTexture, sample.a); src.a = (1.0 - exp( - StepSize * src.a)); } else { /*Pre-Integrated color calc*/ float opacity = 1.0 - exp( - deltaT * StepSize / delta); vec3 color = abs(deltaK) / (abs(deltaT) + 1.0e-10); src = vec4(color, opacity); } lastTransfer = transfer; lastsamplea = sample.a; ////////////Lighting calculations //We perform all the calculations in the eye space, The normal //from the previous step is used, as it is the normal in the //direction the ray entered the volume. vec3 norm = (ViewMatrix * vec4(lastnorm, 0.0)).xyz; src.rgb = calcLighting((ViewMatrix * vec4(rayPos,1.0)).xyz, norm, src.rgb); //Update the lastnormal with the new normal, if it is valid norm = sample.xyz * 2.0 - vec3(1.0); //Test if we've got a bad normal and need to reuse the old one float sqrnormlength = dot(norm,norm); norm /= sqrt(sqrnormlength); if (sqrnormlength >= 0.01) lastnorm = norm; ///////////Front to back blending src.rgb *= src.a; color = (1.0 - color.a) * src + color; //We only accumulate up to 0.95 alpha (the blending never //reaches 1). if (color.a >= 0.95) { //We have to renormalize the color by the alpha value (see //below) color.rgb /= color.a; //Set the alpha to one to make sure the pixel is not transparent color.a = 1.0; break; } } /*We must renormalize the color by the alpha value. For example, if our ray only hits just one white voxel with a alpha of 0.5, we will have src.rgb = vec4(1,1,1,0.5) src.rgb *= src.a; //which gives, src.rgb = 0.5 * src.rgb = vec4(0.5,0.5,0.5,0.5) color = (1.0 - color.a) * src + color; //which gives, color = (1.0 - 0) * vec4(0.5,0.5,0.5,0.5) + vec4(0,0,0,0) = vec4(0.5,0.5,0.5,0.5) So the final color of the ray is half way between white and black, but the voxel it hit was white! The solution is to divide by the alpha, as this is the "amount of color" added to color. */ color.rgb /= float(color.a == 0.0) + color.a; color_out = color; });
void HornerBernstein(in samplerBuffer data, in int offset, in int OrderU, in int OrderV, in vec2 uv, out vec4 du, out vec4 dv, out vec4 point) { int i, j; int n = OrderU - 1; int m = OrderV - 1; float powu, powv, nci, mcj; vec4 tpoint0; vec4 tpointi; vec4 tpointn; //For i == n point = vec4(0.0); //For First and Last Rows tpoint0 = tpointn = vec4(0.0); nci = mcj = powu = powv = 1.0; for ( j = 0; j < m; j++ ) { tpoint0 = (tpoint0 + mcj * powv * texelFetch(data, offset + OrderU * j)) * (1.0 - uv[1]); tpointn = (tpointn + mcj * powv * texelFetch(data, offset + OrderU * j + n)) * (1.0 - uv[1]); mcj *= float(m - j) / float(j + 1); powv *= uv[1]; } tpoint0 = tpoint0 + powv * texelFetch(data, offset + OrderU * j); tpointn = tpointn + powv * texelFetch(data, offset + OrderU * j + n); point = (point + nci * powu * tpoint0) * (1.0 - uv[0]); nci = nci * float(n); powu = powu * uv[0]; //For Remaining Rows for ( i = 1; i < n; i++ ) { tpointi = vec4(0.0); mcj = 1.0; powv = 1.0; for ( j = 0; j < m; j++ ) { tpointi = (tpointi + mcj * powv * texelFetch(data, offset + OrderU * j + i)) * (1.0 - uv[1]); mcj *= float(m - j) / float(j + 1); powv *= uv[1]; } tpointi = tpointi + powv * texelFetch(data, offset + OrderU * j + i); point = (point + nci * powu * tpointi) * (1.0 - uv[0]); nci = nci * float(n - i) / float(i + 1); powu = powu * uv[0]; } point = point + powu * tpointn; //Partial Derivative with respect to u dP/du powu = powv = nci = mcj = 1.0; du = tpoint0 = tpointn = vec4(0.0); for ( j = 0; j < m; j++ ) { tpoint0 = (tpoint0 + mcj * powv * (texelFetch(data, offset + OrderU * j + 1) - texelFetch(data, offset + OrderU * j) ) ) * (1.0 - uv[1]); tpointn = (tpointn + mcj * powv * (texelFetch(data, offset + OrderU * j + n) - texelFetch(data, offset + OrderU * j + n - 1)) ) * (1.0 - uv[1]); mcj *= float(m - j) / float(j + 1); powv *= uv[1]; } tpoint0 = tpoint0 + powv * (texelFetch(data, offset + OrderU * j + 1) - texelFetch(data, offset + OrderU * j)); tpointn = tpointn + powv * (texelFetch(data, offset + OrderU * j + n) - texelFetch(data, offset + OrderU * j + n - 1)); du = (du + nci * powu * tpoint0) * (1.0 - uv[0]); nci = nci * float(n - 1); powu = powu * uv[0]; //For Remaining Rows for ( i = 1; i < n - 1; i++ ) { tpointi = vec4(0.0); mcj = 1.0; powv = 1.0; for ( j = 0; j < m; j++ ) { tpointi = (tpointi + mcj * powv * (texelFetch(data, offset + OrderU * j + i + 1) - texelFetch(data, offset + OrderU * j + i))) * (1.0 - uv[1]); mcj *= float(m - j) / float(j + 1); powv *= uv[1]; } tpointi = tpointi + powv * (texelFetch(data, offset + OrderU * j + i + 1) - texelFetch(data, offset + OrderU * j + i)); du = (du + nci * powu * tpointi) * (1.0 - uv[0]); nci = nci * float(n - i - 1) / float(i + 1); powu = powu * uv[0]; } du = du + powu * tpointn; du = du * n; //Partial Derivative with respect to v dP/dv dv = vec4(0.0); powu = 1.0; powv = 1.0; nci = 1.0; mcj = 1.0; tpoint0 = vec4(0.0); tpointn = vec4(0.0); for ( j = 0; j < m - 1; j++ ) { tpoint0 = (tpoint0 + mcj * powv * ( texelFetch(data, offset + OrderU * (j + 1)) - texelFetch(data, offset + OrderU * j) ) ) * (1.0 - uv[1]); tpointn = (tpointn + mcj * powv * (texelFetch(data, offset + OrderU * (j + 1) + n) - texelFetch(data, offset + OrderU * j + n)) ) * (1.0 - uv[1]); mcj *= float(m - j - 1) / float(j + 1); powv *= uv[1]; } tpoint0 = tpoint0 + powv * (texelFetch(data, offset + OrderU * (j + 1)) - texelFetch(data, offset + OrderU * j)); tpointn = tpointn + powv * (texelFetch(data, offset + OrderU * (j + 1) + n) - texelFetch(data, offset + OrderU * j + n)); dv = (dv + nci * powu * tpoint0) * (1.0 - uv[0]); nci = nci * float(n); powu = powu * uv[0]; //For Remaining Rows for ( i = 1; i < n; i++ ) { tpointi = vec4(0.0); mcj = 1.0; powv = 1.0; for ( j = 0; j < m - 1; j++ ) { tpointi = (tpointi + mcj * powv * (texelFetch(data, offset + OrderU * (j + 1) + i) - texelFetch(data, offset + OrderU * j + i))) * (1.0 - uv[1]); mcj *= float(m - j - 1) / float(j + 1); powv *= uv[1]; } tpointi = tpointi + powv * (texelFetch(data, offset + OrderU * (j + 1) + i) - texelFetch(data, offset + OrderU * j + i)); dv = (dv + nci * powu * tpointi) * (1.0 - uv[0]); nci = nci * float(n - i) / float(i + 1); powu = powu * uv[0]; } dv = dv + powu * tpointn; dv = dv * m; //Transformation from Homogeneous Space to Euclidean Space du = (du * point.w - point * du.w) / pow(point.w, 2); //P.S.: simply p(t) = r(t) / s(t) => p'(t) = (r'(t)s(t)-r(t)s'(t)) / (s(t)^2) ..... dv = (dv * point.w - point * dv.w) / pow(point.w, 2); //P.S.: p(t) = r(t) / s(t) => r(t) = p(t) x s(t) => r'(t) = p'(t)xs(t) + p(t)xs'(t) => p'(t) = ..... doesn't give precise results point = point / point.w; }
void main() { tcPosition[ID] = vPosition[ID]; tcIndex[ID] = vIndex[ID]; tcTessCoord[ID] = vTessCoord[ID]; vec4 data = texelFetch(attribute_texture, int(vIndex[ID]) * 5); if ( frustum_cull() ) { if ( abs(vTessCoord[0].x - vTessCoord[1].x) * abs(vTessCoord[1].y - vTessCoord[2].y) == 1.0 ) { vec4 curve_factor = clamp(texelFetch(attribute_texture, int(vIndex[ID]) * 5 + 4), 1, 4); vec4 edgelen = control_polygon_length(parameter_texture, int(data.x), int(data.y), int(data.z)); // 2 // 2------3 //3 | | 1 // | | // 0------1 // 0 float edge01 = edge_tesslevel(edgelen[0]); float edge32 = edge_tesslevel(edgelen[2]); float edge13 = edge_tesslevel(edgelen[1]); float edge20 = edge_tesslevel(edgelen[3]); //Following three must be same for Ist Pass gl_TessLevelInner[0] = inner_tesslevel(); gl_TessLevelOuter[1] = edge01; gl_TessLevelOuter[3] = edge32; //Following three must be same for Ist Pass gl_TessLevelInner[1] = inner_tesslevel(); gl_TessLevelOuter[0] = edge20; gl_TessLevelOuter[2] = edge13; } else { vec4 point_on_plane0 = to_screen_space(vPosition[0]); vec4 point_on_plane1 = to_screen_space(vPosition[1]); vec4 point_on_plane2 = to_screen_space(vPosition[2]); vec4 point_on_plane3 = to_screen_space(vPosition[3]); //Approach I-----> For Outer Tessellation Levels : Take ratio according to the original control polygon length. // For Inner Tessellation Levels : Evaluate the mid point of the patch and get the diagonal length. vec4 edgelen = control_polygon_length(parameter_texture, int(data.x), int(data.y), int(data.z)); vec2 p1 = mix(vTessCoord[0].xy, vTessCoord[1].xy, 0.5); vec2 p2 = mix(vTessCoord[3].xy, vTessCoord[2].xy, 0.5); vec2 mid_uv = mix(p1, p2, 0.5); vec4 du, dv, _puv; HornerBernstein(parameter_texture, int(data.x), int(data.y), int(data.z), mid_uv, du, dv, _puv); _puv = to_screen_space(_puv.xyz); float length1 = length(point_on_plane0.xy - _puv.xy) + length(_puv.xy - point_on_plane3.xy); float length2 = length(point_on_plane2.xy - _puv.xy) + length(_puv.xy - point_on_plane1.xy); float diagonal_length = min(length1, length2); float edge01 = edge_tesslevel(mix(edgelen[0], edgelen[2], abs(vTessCoord[0].y - vTessCoord[2].y))); float edge32 = edge_tesslevel(mix(edgelen[0], edgelen[2], abs(vTessCoord[0].y - vTessCoord[2].y))); float edge13 = edge_tesslevel(mix(edgelen[1], edgelen[3], abs(vTessCoord[0].x - vTessCoord[1].x))); float edge20 = edge_tesslevel(mix(edgelen[1], edgelen[3], abs(vTessCoord[0].x - vTessCoord[1].x))); /*****/ //Approach II-----> For Outer Tessellation Levels : Approximate the curvature length of the edge according to the angle between its normals. // For Inner Tessellation Levels : Approximate the curvature of the surface according to the all edge normals. //Normals projected in XY-Plane /* vec2 normal0 = normalize(transpose(inverse(mat3(view_matrix * model_matrix))) * vNormal[0].xyz).xy; vec2 normal1 = normalize(transpose(inverse(mat3(view_matrix * model_matrix))) * vNormal[1].xyz).xy; vec2 normal2 = normalize(transpose(inverse(mat3(view_matrix * model_matrix))) * vNormal[2].xyz).xy; vec2 normal3 = normalize(transpose(inverse(mat3(view_matrix * model_matrix))) * vNormal[3].xyz).xy; float edge01 = edge_tesslevel(length(point_on_plane0 - point_on_plane1) * acos(dot(normal0, normal1)) / (2.0 * sin(acos(dot(normal0, normal1) / 2.0)))); float edge32 = edge_tesslevel(length(point_on_plane3 - point_on_plane2) * acos(dot(normal3, normal2)) / (2.0 * sin(acos(dot(normal3, normal2) / 2.0)))); float edge13 = edge_tesslevel(length(point_on_plane1 - point_on_plane3) * acos(dot(normal1, normal3)) / (2.0 * sin(acos(dot(normal1, normal3) / 2.0)))); float edge20 = edge_tesslevel(length(point_on_plane2 - point_on_plane0) * acos(dot(normal2, normal0)) / (2.0 * sin(acos(dot(normal2, normal0) / 2.0))));*/ //Following three must be same for Ist Pass gl_TessLevelInner[0] = edge_tesslevel(diagonal_length); gl_TessLevelOuter[1] = edge01; gl_TessLevelOuter[3] = edge32; //Following three must be same for Ist Pass gl_TessLevelInner[1] = edge_tesslevel(diagonal_length); gl_TessLevelOuter[0] = edge20; gl_TessLevelOuter[2] = edge13; } } else { gl_TessLevelInner[0] = 1; gl_TessLevelOuter[1] = 1; gl_TessLevelOuter[3] = 1; gl_TessLevelInner[1] = 1; gl_TessLevelOuter[0] = 1; gl_TessLevelOuter[2] = 1; } }