How to use Cubemape with samplerCube In a Shader?

Hey there THREE.JS kupos! I’m wondering if I could get a bit of insight, as I’m sure I’m doing something stupid.

The basic question.

When I try to pass the cubemap from THREE.CubemapTextureLoader as a shader uniform of type samplerCube, and use textureCube to read the color information in a fragment shader. I’m getting nothing but a black screen.

https://jsfiddle.net/Dante83/qkh0x2c5/75/

This is a bit contrived, but I believe it gives the basics of what I’m talking about.

Why do I need this?


Introduction wise, at a 30,000 foot viewpoint, I’m trying to update my sky with faster procedural stars for a sky shader program. This is the previous version 0.3.0, that you can open IFF (If and only if) you have a desktop (It’s designed for A-Frame, but that’s mostly a thin wrapper for most of the code).

(Don’t open on mobile, it’s simply too heavy)

http://code-panda.com/pages/projects/v_0_3_0/a_sky_forge_example

From what I’ve seen, the stars are the heaviest bit of code in every version. Even in the latest version, each texel in the fragment shader converts the x, y, z location into right ascension and declination, and two texture lookups give the coordinates for 4 stars on a set of 8-bit data textures. Another 4 texture lookups are done for each of these stars to get the exact positions, a color and brightness. The colors are converted from colors into float and the distance from the text to the star is calculated via the haversine distance to determine the brightness of the texel.

It works great, but it’s a massive GPU hog. Also, I need to do real spectral blackbody stuff to get the true color of the stars. Guh. (18 texture look ups and lots of trigonometry for each star)

This is where the new algorithm comes in that I’m taking a shot at.


In the new algorithm, I started by grouping my stars together by nearest neighbors until I had a continuous line, these are my data textures. Because nearest neighbors are emphasized in the grouping, the pixels to the left and right are generally the ids of nearby stars if they’re very close. This keeps them grouped together on the data texture, and it means I can use one id to drive my lookups. I’m also employing floating point textures right off the bat, so instead of having 4 texture lookups per star, I only need 1 per star (this time using r,g,b,a to store the normalized x, y, z coordinates of the star, the magnitude of the star and I hide the temperature in the normalized x, y, z coordinates).

Although I might be gaining some texture lookups back by employing lookups for the spectral information, or to simulate the twinkling noise, these are generally net gains for the future. Overall, I could use this method to reduce my number of texture look ups from 18 to 5 if I wanted to while dramatically reducing the number of calculations per star.

One of the ways I hoped to reduce the number of computations was to store my lookup ids for the closest star inside of cubemap instead of the traditional 2-D map. In the previous version, for every texel and frame, I needed to convert my coordinates to right ascension and declination normalized between 0 and 1. What I wanted to do this time was to just pass the vector for the texel into the cubemap and grab the coordinates. I might still do some transformations as I’m converting world space into galactic coordinates, but I can do that in the vertex shader. However, normalizing that vector on every fragment is pretty cheap compared to all the math I need to change it out with normalized az-alt from before.

Unfortunately, with a black cubemap, I can’t grab the RGB information I need to get my Ids.

Hopefully someone knows why I can’t get colors from my cubemap texture locations. At least I was able to duplicate it in the fiddle above, as the code itself is a bit complicated:

And Chrome is choking on my web assembly again for some reason, “Come on Chrome, get it together! What did you change this time without telling me?!”

Thank you for looking at my question!

-Dante

I’m not sure what you are doing with baseEncodedImage but using an external cube map from the official repository makes the demo work.

2 Likes

Woah! Yes! I’m sorry about the baseEncodedImage, I tried grabbing an image from elsewhere as an example. Thinking back, I wonder if it wasn’t perfectly square (Not always familiar with JS fiddle and didn’t know I could grab images through cross-origin like that). But at least I have a working example I can search through so I can try and figure out just what’s going on in the main code branch.

Thank you very much!
-Dante

I just wanted to say I got it working on the other branch. I’m not sure what I needed to exactly change, but I believe either the texture wasn’t getting updated after I loaded it, or was getting an update request that somehow cleared out the previous texture? I’m not sure because it wasn’t working, I went to change something else and then it started to working and changing back didn’t cause it to stop. Maybe I don’t know all the points where I need to check for this in the asynchronous loading.

As you can tell from the seems, I also have incorrect textures, but I think I should have something to work so I can hunt down that bug. I’m creating my cube maps pixel by pixel in python so - fun times ahead :D. At least now I feel like the major hurdle to trying out my idea is gone. Thank you again!