Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changing VOLUME_RENDERING from string to integer #729

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

fcollman
Copy link
Contributor

I wanted to make a shader that did a variable local maximum projection in the slice view (with color coding for depth). Like this... but to make the shader compiliation not balk, i have to avoid using variables that are not defined during the volume rendering pass. Without modifying the source code of neuroglancer, I think i have to do this with header macros, but the current VOLUME_RENDERING header is a string 'true' or 'false' which means i can't use to do conditional pre-compilation macros myself.

Perhaps there is another workaround for this case, but it seemed to me that if we switched to using simple integers for VOLUME_RENDERING, this would let me do what i needed to accomplish this shader.

I'm submitting this as PR/issue to see what @jbms and @seankmartin think is the best approach here.

#uicontrol int zrange slider(min=0, max=15)
#uicontrol invlerp normalized
#if VOLUME_RENDERING
    // If VOLUME_RENDERING is defined at compile time,
    // use curChunkPosition
    #define CHUNK_POSITION curChunkPosition
    #define PLANE_NORMAL vec3(1.0,0.0,0.0)
#else
    // Otherwise, use vChunkPosition
    #define CHUNK_POSITION vChunkPosition
    #define PLANE_NORMAL uPlaneNormal
#endif
  
void main() {
    if (VOLUME_RENDERING==1){
        float norm = normalized();
        emitRGBA(vec4(norm, norm, norm, norm));
    }
  else{
    ivec3 p = ivec3(max(vec3(0.0), 
                        min(floor(CHUNK_POSITION), uChunkDataSize - 1.0)));
    uint channel0_data = getDataValueAt(p).value;
    
    // We'll hold the best intensity and best offset
    uint best_val = channel0_data;
    int max_z = 0;  // offset found for the best value
    
    // If zrange > 0, do the searching; if zrange == 0, skip
    if (zrange > 0) {
        // Search "above" or plus side
        vec3 p_tmp = vec3(p);
        for(int i = 1; i <= zrange; i++) {
            p_tmp += PLANE_NORMAL;  // or -=, depending on your orientation
            ivec3 p_check = ivec3(max(vec3(0.0), p_tmp));
            uint val = getDataValueAt(p_check).value;
            if (val > best_val) {
                best_val = val;
                max_z = i;
            }
        }

        // Search "below" or minus side
        p_tmp = vec3(p);
        for(int i = 1; i <= zrange; i++) {
            p_tmp -= PLANE_NORMAL;  // opposite direction
            ivec3 p_check = ivec3(max(vec3(0.0), p_tmp));
            uint val = getDataValueAt(p_check).value;
            if (val > best_val) {
                best_val = val;
                max_z = -i;
            }
        }
    }
    else {
        // zrange = 0, so we do NOT search;
        // keep best_val = channel0_data and max_z = 0
    }
    
    // ratio in [-1, 1]
    float ratio = 0.0;
    if (zrange != 0) {
        ratio = float(max_z) / float(zrange);
    }
    ratio = clamp(ratio, -1.0, 1.0);

    // Define key colors
    vec3 white = vec3(1.0, 1.0, 1.0);
    vec3 red   = vec3(1.0, 0.0, 0.0);
    vec3 blue  = vec3(0.0, 0.0, 1.0);

    // Map ratio to color
    vec3 color;
    if (ratio > 0.0) {
        color = mix(white, red, ratio);
    } else if (ratio < 0.0) {
        color = mix(white, blue, -ratio); 
    } else {
        color = white;  // ratio == 0
    }

    // Use the data value for brightness/alpha
    float alpha = normalized(best_val);

    emitRGBA(vec4(color * alpha, alpha));
  }
}

this works locally quite nicely..

image

@fcollman
Copy link
Contributor Author

also, this doesn't quite work right across chunk boundaries, not sure if there is something that could be done about that.

@jbms
Copy link
Collaborator

jbms commented Feb 14, 2025

Changing the value of the existing define could break existing shaders. Potentially it could be made to work in #if though either by defining a different macro to 1 and 0, or applying some code transformations so that it somehow works in #if anyway

Separately, though, while your max projection is a cool idea, you are relying on implementation details that may well change, and as you noted it doesn't work across chunk boundaries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants