Skip to content

consolidate GLSL#582

Merged
TheJeran merged 2 commits intomainfrom
jp/glsl-condense
Mar 12, 2026
Merged

consolidate GLSL#582
TheJeran merged 2 commits intomainfrom
jp/glsl-condense

Conversation

@TheJeran
Copy link
Collaborator

For shaders that needed different logic for if the texture fed into it were 2D or 3D,

I learned you can use #ifdef to create conditional compilation. So I consolidated those shaders into one shader, and made a function to append the IS_FLAT method if I need to use the 2D variant code

@TheJeran TheJeran linked an issue Mar 11, 2026 that may be closed by this pull request
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on improving the structure and maintainability of GLSL shaders by consolidating similar shaders and introducing dynamic shader selection. This approach reduces redundancy and simplifies the codebase, making it easier to manage and update shaders in the future.

Highlights

  • Shader Consolidation: Consolidated separate GLSL shaders for 2D and 3D textures into single shaders using #ifdef for conditional compilation, reducing code duplication.
  • Dynamic Shader Selection: Introduced GetFrag and GetVert functions to dynamically select fragment and vertex shaders based on the isFlat property, enhancing code maintainability.
  • Code Reorganization: Removed redundant shader files and updated component files to utilize the new shader selection logic, streamlining the codebase.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/components/plots/DataCube.tsx
    • No significant changes were made to this file.
  • src/components/plots/FlatBlocks.tsx
    • Refactored to use GetVert for dynamic vertex shader selection based on the isFlat property.
    • Removed direct imports of flatBlocksVert and flatBlocksVert3D.
  • src/components/plots/FlatMap.tsx
    • Updated to use GetFrag for dynamic fragment shader selection based on the isFlat property.
    • Removed direct imports of flatFrag3D and fragmentFlat.
  • src/components/plots/Sphere.tsx
    • Refactored to use GetFrag and GetVert for dynamic shader selection based on the isFlat property.
    • Removed direct imports of specific sphere shaders.
  • src/components/plots/SphereBlocks.tsx
    • Refactored to use GetVert for dynamic vertex shader selection based on the isFlat property.
    • Removed direct imports of sphereBlocksVert and sphereBlocksVertFlat.
  • src/components/textures/GetFrag.ts
    • Added a new file to handle dynamic fragment shader selection based on the isFlat property.
  • src/components/textures/GetVert.ts
    • Added a new file to handle dynamic vertex shader selection based on the isFlat property.
  • src/components/textures/index.ts
    • Exported GetFrag and GetVert functions.
  • src/components/textures/shaders/flatBlocksVert.glsl
    • Modified to include conditional compilation using #ifdef IS_FLAT for handling 2D and 3D textures.
    • Updated sample1 function to accept vec2 or vec3 based on IS_FLAT definition.
  • src/components/textures/shaders/flatBlocksVert3D.glsl
    • Removed the file as its functionality is now incorporated into flatBlocksVert.glsl.
  • src/components/textures/shaders/flatFrag.glsl
    • Renamed from flatFrag3D.glsl and modified to include conditional compilation using #ifdef IS_FLAT for handling 2D and 3D textures.
    • Updated sample1 function to accept vec2 or vec3 based on IS_FLAT definition.
  • src/components/textures/shaders/fragmentFlat.glsl
    • Removed the file as its functionality is now incorporated into flatFrag.glsl.
  • src/components/textures/shaders/index.ts
    • Removed exports for the shaders that were consolidated.
  • src/components/textures/shaders/sphereBlocksVert.glsl
    • Modified to include conditional compilation using #ifdef IS_FLAT for handling 2D and 3D textures.
    • Updated sample1 function to accept vec2 or vec3 based on IS_FLAT definition.
  • src/components/textures/shaders/sphereBlocksVertFlat.glsl
    • Removed the file as its functionality is now incorporated into sphereBlocksVert.glsl.
  • src/components/textures/shaders/sphereFrag.glsl
    • Modified to include conditional compilation using #ifdef IS_FLAT for handling 2D and 3D textures.
    • Updated sample1 function to accept vec2 or vec3 based on IS_FLAT definition.
    • Added conditional compilation to disable selectTS when IS_FLAT is defined.
  • src/components/textures/shaders/sphereVertex.glsl
    • Modified to include conditional compilation using #ifdef IS_FLAT for handling 2D and 3D textures.
    • Updated sample1 function to accept vec2 or vec3 based on IS_FLAT definition.
  • src/components/textures/shaders/sphereVertexFlat.glsl
    • Removed the file as its functionality is now incorporated into sphereVertex.glsl.
Activity
  • The author, TheJeran, consolidated GLSL shaders to reduce code duplication and improve maintainability.
  • Conditional compilation using #ifdef was implemented to handle different logic for 2D and 3D textures within the same shader.
  • GetFrag and GetVert functions were introduced to dynamically select shaders based on the isFlat property.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors shader management by introducing GetFrag and GetVert utility functions to dynamically load and preprocess GLSL shaders with an IS_FLAT directive. This consolidates shader logic, eliminating several redundant *Flat.glsl files and simplifying shader usage across components like FlatBlocks, FlatMap, Sphere, and SphereBlocks. The review identified a critical compilation error in sphereVertex.glsl where the normal variable is used conditionally without being universally defined, and suggested improving type safety in GetVert.ts by using keyof typeof shaders and abstracting common logic between GetVert and GetFrag to reduce code duplication.

Comment on lines 54 to 91
void main() {
vec2 uv = giveUV(position); // We can't just pass this as a varying because the fragment will try to interpoalte between the seems which looks bad
bool inBounds = all(greaterThanEqual(uv, vec2(0.0))) &&
all(lessThanEqual(uv, vec2(1.0)));
aPosition = position;
if (inBounds){
vec3 normal = normalize(position);
int zStepSize = int(textureDepths.y) * int(textureDepths.x);
int yStepSize = int(textureDepths.x);
vec3 texCoord = vec3(uv, animateProg);
ivec3 idx = clamp(ivec3(texCoord * textureDepths), ivec3(0), ivec3(textureDepths) - 1); // Ivec3 is like running a "floor" operation on all three at once. The clamp is because the very last idx is OOR
int textureIdx = idx.z * zStepSize + idx.y * yStepSize + idx.x;
vec3 localCoord = texCoord * textureDepths; // Scale up
int yStepSize = int(textureDepths.x);
#ifdef IS_FLAT
ivec2 idx = clamp(ivec2(uv * textureDepths.xy), ivec2(0), ivec2(textureDepths.xy) - 1);
int textureIdx = idx.y * yStepSize + idx.x;
vec2 localCoord = uv * (textureDepths.xy); // Scale up
localCoord = fract(localCoord);
float dispStrength = sample1(localCoord, textureIdx);
float noNan = float(dispStrength != 1.0);
vec3 newPos = position + (normal * (dispStrength-displaceZero) * noNan * displacement);
//Pass out position for sphere frag
aPosition = position; //Pass out position for sphere frag
vec4 worldPos = modelViewMatrix * vec4( newPos, 1.0 );
gl_Position = projectionMatrix * worldPos;
} else {
vec4 worldPos = modelViewMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * worldPos;
}


#else
bool inBounds = all(greaterThanEqual(uv, vec2(0.0))) &&
all(lessThanEqual(uv, vec2(1.0)));
aPosition = position;
if (inBounds){
vec3 normal = normalize(position);
int zStepSize = int(textureDepths.y) * int(textureDepths.x);
vec3 texCoord = vec3(uv, animateProg);
ivec3 idx = clamp(ivec3(texCoord * textureDepths), ivec3(0), ivec3(textureDepths) - 1); // Ivec3 is like running a "floor" operation on all three at once. The clamp is because the very last idx is OOR
int textureIdx = idx.z * zStepSize + idx.y * yStepSize + idx.x;
vec3 localCoord = texCoord * textureDepths; // Scale up
localCoord = fract(localCoord);
float dispStrength = sample1(localCoord, textureIdx);
float noNan = float(dispStrength != 1.0);
vec3 newPos = position + (normal * (dispStrength-displaceZero) * noNan * displacement);
//Pass out position for sphere frag
vec4 worldPos = modelViewMatrix * vec4( newPos, 1.0 );
gl_Position = projectionMatrix * worldPos;
} else {
vec4 worldPos = modelViewMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * worldPos;
}
#endif
} No newline at end of file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

There's a compilation error in the #ifdef IS_FLAT branch. The normal variable is used on line 64, but it's only defined within the #else block (on line 73). This will cause the shader to fail to compile when isFlat is true.

To fix this, you should define normal before the #ifdef block, so it's available in both branches.

void main() {
    vec2 uv = giveUV(position); // We can't just pass this as a varying because the fragment will try to interpoalte between the seems which looks bad 
    vec3 normal = normalize(position);
    int yStepSize = int(textureDepths.x); 
    #ifdef IS_FLAT
        ivec2 idx = clamp(ivec2(uv * textureDepths.xy), ivec2(0), ivec2(textureDepths.xy) - 1);
        int textureIdx = idx.y * yStepSize + idx.x;
        vec2 localCoord = uv * (textureDepths.xy); // Scale up
        localCoord = fract(localCoord);
        float dispStrength = sample1(localCoord, textureIdx);
        float noNan = float(dispStrength != 1.0);
        vec3 newPos = position + (normal * (dispStrength-displaceZero) * noNan * displacement);
        aPosition = position; //Pass out position for sphere frag
        vec4 worldPos = modelViewMatrix * vec4( newPos, 1.0 );
        gl_Position = projectionMatrix * worldPos;
    #else
        bool inBounds = all(greaterThanEqual(uv, vec2(0.0))) && 
                    all(lessThanEqual(uv, vec2(1.0)));
        aPosition = position;
        if (inBounds){
            int zStepSize = int(textureDepths.y) * int(textureDepths.x); 
            vec3 texCoord = vec3(uv, animateProg);
            ivec3 idx = clamp(ivec3(texCoord * textureDepths), ivec3(0), ivec3(textureDepths) - 1); // Ivec3 is like running a "floor" operation on all three at once. The clamp is because the very last idx is OOR
            int textureIdx = idx.z * zStepSize + idx.y * yStepSize + idx.x;
            vec3 localCoord = texCoord * textureDepths; // Scale up
            localCoord = fract(localCoord);
            float dispStrength = sample1(localCoord, textureIdx);
            float noNan = float(dispStrength != 1.0);
            vec3 newPos = position + (normal * (dispStrength-displaceZero) * noNan * displacement);
            //Pass out position for sphere frag
            vec4 worldPos = modelViewMatrix * vec4( newPos, 1.0 );
            gl_Position = projectionMatrix * worldPos;
        } else {
            vec4 worldPos = modelViewMatrix * vec4( position, 1.0 );
            gl_Position = projectionMatrix * worldPos;
        }
    #endif
}

Comment on lines +9 to +16
export const GetVert = (shader:string, isFlat: boolean) => {
const vert = shaders[shader as keyof typeof shaders]
const prefix = isFlat ? "#define IS_FLAT\n" : "";
const output = prefix + vert;
return (
output
)
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The function signature for GetVert uses shader: string and then casts it, which is not type-safe. You can improve this by using keyof typeof shaders directly in the function signature for compile-time checking of the shader name.

Additionally, the logic inside GetVert is identical to the logic in GetFrag. You could abstract this into a single generic function to reduce code duplication and improve maintainability.

Suggested change
export const GetVert = (shader:string, isFlat: boolean) => {
const vert = shaders[shader as keyof typeof shaders]
const prefix = isFlat ? "#define IS_FLAT\n" : "";
const output = prefix + vert;
return (
output
)
}
export const GetVert = (shader: keyof typeof shaders, isFlat: boolean) => {
const vert = shaders[shader];
const prefix = isFlat ? "#define IS_FLAT\n" : "";
const output = prefix + vert;
return (
output
)
}

@TheJeran TheJeran merged commit 602487d into main Mar 12, 2026
6 checks passed
@TheJeran TheJeran deleted the jp/glsl-condense branch March 12, 2026 08:56
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.

Consolidate duplicate GLSL Code

1 participant