Skip to content

Conversation

@sshcrack
Copy link
Contributor

Fixes #6 (not sure if it breaks other cubemaps)

Copy link
Owner

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

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

[
    {
        "inputs": [
            {
                "id": "4dX3Rr",
                "filepath": "/media/a//media/previz/cubemap00.png",
                "previewfilepath": "/media/ap//media/previz/cubemap00.png",
                "type": "cubemap",
                "channel": 0,
                "sampler": {
                    "filter": "mipmap",
                    "wrap": "clamp",
                    "vflip": "true",
                    "srgb": "false",
                    "internal": "byte"
                },
                "published": 1
            }
        ],
        "outputs": [
            {
                "id": "4dfGRr",
                "channel": 0
            }
        ],
        "code": "#define rot(a) mat2( sin(a+vec4(0,33,11,0)) )  // https://www.shadertoy.com/view/XlsyWX\n\n#define F0 vec3( 1 , 1.- 2.*(U/R).yx )                 // to index each face map\n#define F1 vec3( 2.*(U/R).x -1. , 1 , 2.*(U/R).y -1. )\n#define F2 vec3( 2.*(U/R).x -1. , 1.- 2.*(U/R).y , 1 )\n\nvoid mainImage( out vec4 O, in vec2 U )\n{\n    vec2 R = iResolution.xy;\n    float FOV = .5;\n    vec3 D = normalize( vec3( 1./FOV, (U+U-R)/R.y ) ); // ray direction\n//  Note that D see faceID 0, -D see faceID 3\n//            D.zxy    \"   1, -D.zxy   \"    4 \n//            D.yzx    \"   2, -D.yzx   \"    5\n//  see F0,F1,F2 for accurate indexing of face maps.\n    \n    D.xz *= rot(iTime/2.);\n    D.yz *= rot(iTime/2.);               \n   \n    O = texture( iChannel0, D );\n}",
        "name": "Image",
        "description": "",
        "type": "image"
    },
    {
        "inputs": [],
        "outputs": [
            {
                "id": "4dXGR8",
                "channel": 0
            }
        ],
        "code": "#define hue(v)  ( .6 + .6 * cos( 6.3*(v)  + vec4(0,23,21,0)  ) ) // https://www.shadertoy.com/view/ll2cDc\n\nvoid mainCubemap( out vec4 O, vec2 U, vec3 C, vec3 D ) // note that C==vec3(0)\n    //           out Color, MapCoord, Center(=0), rayDir\n{\n    // --- part specific to each of the 6 faces\n    \n    vec3 A = abs(D); // seek for max direction: i = invmax(abs(D[i]))\n    int i=0; \n    float      M = A.x; \n    if (A.y>M) M = A.y, i=1;\n    if (A.z>M) M = A.z, i=2;\n    int  faceID = i + 3* int(D[i]<0.);\n    \n    O = hue(float(faceID)/6.);\n    \n    \n    // --- part indentical on the 6 faces\n    \n    vec2 R = iResolution.xy; // always 1024\n    U = ( U+U - R ) / R.y;\n    O *= vec4( .8+.2*sin(34.*length(U)) );\n}\n",
        "name": "Cube A",
        "description": "",
        "type": "cubemap"
    }
]

The input channel ID does not necessarily equal the output channel ID.
Can you tell what Shadertoy does in this case? Does cubemap00.png mean cube A?

@sshcrack
Copy link
Contributor Author

I found this piece of code:

function assetID_to_cubemapBuferID( id )
{
    if( id==='4dX3Rr' ) return 0;
    return -1;
}
// ...
if( assetID_to_cubemapBuferID(url.mID)!==-1 )
        {
            texture.mImage = new Image();
            texture.mImage.onload = function()
            {
                texture.loaded = true;
                if( me.mTextureCallbackFun!==null )
                    me.mTextureCallbackFun( me.mTextureCallbackObj, slot, texture.mImage, true, 2, 1, -1.0, me.mID );
            }
            texture.mImage.src = "/media/previz/cubemap00.png";

            this.mEffect.ResizeCubemapBuffer(0, 1024, 1024 );

        }
        else
        {
            texture.image = [ new Image(), new Image(), new Image(), new Image(), new Image(), new Image() ];

            let numLoaded = 0;
            for (var i=0; i<6; i++ )
            {
                texture.image[i].mId = i;
                texture.image[i].crossOrigin = '';
                texture.image[i].onload = function()
                {
                    var id = this.mId;
                    numLoaded++;
                    if( numLoaded===6 )
                    {
                        texture.globject = renderer.CreateTextureFromImage(renderer.TEXTYPE.CUBEMAP, texture.image, renderer.TEXFMT.C4I8, rti.mFilter, rti.mWrap, rti.mVFlip);
                        texture.loaded = true;
                        if (me.mTextureCallbackFun !== null)
                            me.mTextureCallbackFun(me.mTextureCallbackObj, slot, texture.image[0], true, 2, 1, -1.0, me.mID);
                    }
                }

                if( i === 0) 
                {
                    texture.image[i].src = url.mSrc;
                } 
                else 
                {
                    let n = url.mSrc.lastIndexOf(".");
                    texture.image[i].src = url.mSrc.substring(0, n) + "_" + i + url.mSrc.substring(n, url.mSrc.length);
                }
            }
        }

@sshcrack
Copy link
Contributor Author

sshcrack commented Jul 29, 2025

Actually, this turns out to be much simpler, let me update (I'll use clang format before this is merged because handling two different codebases (one headless the other one with ui) is quite stressful

};
std::unordered_set<std::string> passIds;
// Look at any index.html at EffectPass.prototype.NewTexture if(assetID_to_cubemapBuferId)
const auto isDynamicCubeMap = [&](nlohmann::json& tex) {
Copy link
Owner

Choose a reason for hiding this comment

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

Unused?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, this is just a comment why I've changed it like the way I did (for a few other shaders including https://www.shadertoy.com/view/Xlcczj)

function assetID_to_cubemapBuferID( id )
{
    if( id==='4dX3Rr' ) return 0;
    return -1;
}

This method just checks if it is a dynamic cube map as far as my understanding goes

Copy link
Owner

Choose a reason for hiding this comment

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

/home/runner/work/shadertoy/shadertoy/shadertoy/NodeEditor/PipelineEditor.cpp:1677:20: error: ‘dynamicCubeMap’ was not declared in this scope; did you mean ‘isDynamicCubeMap’?
1677 | if(dynamicCubeMap) {
| ^~~~~~~~~~~~~~
| isDynamicCubeMap

@sshcrack
Copy link
Contributor Author

I'm very close to a fix I think but I'm still facing this issue and I just can't solve it:

I'm using this shadertoy to debug: https://www.shadertoy.com/view/t3cSRl

Right now with my implementation (currently at https://github.com/sshcrack/shadertoy-headless using the debug-window preset)
the sphere turns out to be this:
image

Do you happen to know why?

@dtcxzyw
Copy link
Owner

dtcxzyw commented Jul 29, 2025

Looks like the order of the 6 textures is incorrect, or some faces need to be flipped.

@sshcrack sshcrack marked this pull request as ready for review July 30, 2025 12:50
@dtcxzyw
Copy link
Owner

dtcxzyw commented Jul 30, 2025

I'm using this shadertoy to debug: https://www.shadertoy.com/view/t3cSRl

I disabled the VFlip flag on the iChannel0, and nothing happened. Should we always flip the Y coordinate of vertices for cubemap render targets?

@sshcrack
Copy link
Contributor Author

sshcrack commented Jul 30, 2025

Yeah, this is a bug in the codebase of shadertoy. I've decided to make read the vflip property of the input. If the shadertoy dev decides to fix that bug, we don't need to adjust the code anymore
Every shadertoy I saw with cubemaps had the vflip property enabled, I think the only way to disable vflip is by doing custom POST requests

@sshcrack
Copy link
Contributor Author

I've disabled the vflip property using the custom request method but it seems like this doesn't affect the renderer
See
https://www.shadertoy.com/view/t3cSRl
and
https://www.shadertoy.com/view/WXcSzs


// For Y-flipped cubemaps, also flip Y coordinates of all faces
// to match ShaderToy's UNPACK_FLIP_Y_WEBGL behavior
if(mType == NodeType::CubeMapFlippedY) {
Copy link
Owner

@dtcxzyw dtcxzyw Jul 30, 2025

Choose a reason for hiding this comment

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

I commented out the Y-flipping logic and the result is correct:
image

I think the changes to cube vertex indices are enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is so the cubemaps are actually flipped.
This is how the output should look like:
image
(Notice that the red color is on the top left instead of bottom left)

@sshcrack
Copy link
Contributor Author

sshcrack commented Jul 30, 2025

The changes to vertices broke the voxel shader: https://www.shadertoy.com/view/ssf3zH, I don't know how to fix this yet.
This is weird because the shader doesn't even use CubeMaps. Is this bug occurring because of a previous commit?

@dtcxzyw
Copy link
Owner

dtcxzyw commented Jul 30, 2025

The changes to vertices broke the voxel shader: https://www.shadertoy.com/view/ssf3zH, I don't know how to fix this yet. This is weird because the shader doesn't even use CubeMaps. Is this bug occurring because of a previous commit?

image It works on my side (NVIDIA RTX 4060 Laptop).

@sshcrack
Copy link
Contributor Author

Oh sorry, didn't check out to this codebase, works for me as well. I've got this bug at shadertoy-headless

@dtcxzyw
Copy link
Owner

dtcxzyw commented Jul 30, 2025

Yeah, this is a bug in the codebase of shadertoy. I've decided to make read the vflip property of the input. If the shadertoy dev decides to fix that bug, we don't need to adjust the code anymore
Every shadertoy I saw with cubemaps had the vflip property enabled, I think the only way to disable vflip is by doing custom POST requests

I don‘t like to add a new node type for this workaround. Just flip Y for all cubemaps.

@sshcrack
Copy link
Contributor Author

Okay, will do

sshcrack added 2 commits July 30, 2025 17:02
fix(render): Fix grayscale volumes (dtcxzyw#8)
@sshcrack sshcrack changed the title fix: Use other method to identify dynamic cube maps fix: Always vflip cubemaps Jul 30, 2025
Copy link
Owner

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

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

LGTM.

@dtcxzyw dtcxzyw merged commit 7192f6d into dtcxzyw:main Jul 30, 2025
4 checks passed
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.

Simple cubemap shaders are not working

2 participants