google / filament

Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WebGL2
https://google.github.io/filament/
Apache License 2.0
17.63k stars 1.86k forks source link

IBL Cubemap black #3521

Closed abbana closed 3 years ago

abbana commented 3 years ago

Hi,

Aim: Indirect light specular reflection as solid color (white)

Platform: Java Android , derived from Sceneform

Source: PNG RGB color 8 bits/channel

Request: I think I messed up with the PNG or with the data type. Setting com.google.android.filament.Texture.Type.UINT_10F_11F_11F_REV all the scene becomes black regardless the material and the sun has no effect Setting com.google.android.filament.Texture.Type.HALF metallic objects have just the sun but no reflections (black)

What done:

  com.google.android.filament.IndirectLight buildIndirectLight() {

    Preconditions.checkNotNull(irradianceData, "\"irradianceData\" was null.");
    Preconditions.checkState(
            irradianceData.length >= FLOATS_PER_VECTOR,
            "\"irradianceData\" does not have enough components to store a vector");

    if (reflectCubemap == null) {
      throw new IllegalStateException("reflectCubemap is null.");
    }

    // Modulates ambient color with modulation factor. irradianceData must have at least one vector
    // of three floats.
    irradianceData[0] = ambientColor.r * colorCorrection.r;
    irradianceData[1] = ambientColor.g * colorCorrection.g;
    irradianceData[2] = ambientColor.b * colorCorrection.b;

    IEngine engine = EngineInstance.getEngine();

    /** READ THE 8BIT RGB 1 PIXEL PNG**/
    Bitmap oneWhitePixelBitmap = BitmapFactory.decodeResource(lightProbeContext.getResources(), R.drawable.plane1x1white);

    /** FACE OFFSETS , 4 BYTE EACH FACE
     * CUBEMAP_FACE_COUNT = 6
     * **/
    int[] faceOffsets = new int[CUBEMAP_FACE_COUNT];
    faceOffsets[0] = 0;
    faceOffsets[1] = 4;
    faceOffsets[2] = 8;
    faceOffsets[3] = 12;
    faceOffsets[4] = 16;
    faceOffsets[5] = 20;

    /** CREATE THE BYTEBUFFER AND REWIND
     * After this method returns, the current position of the buffer is updated: the position is incremented by the number of elements written in the buffer.
     * RGBM_BYTES_PER_PIXEL = 4
     * **/
    ByteBuffer oneWhitePixelBuffer = ByteBuffer.allocateDirect( CUBEMAP_FACE_COUNT * RGBM_BYTES_PER_PIXEL);
    oneWhitePixelBitmap.copyPixelsToBuffer(oneWhitePixelBuffer);
    oneWhitePixelBitmap.copyPixelsToBuffer(oneWhitePixelBuffer);
    oneWhitePixelBitmap.copyPixelsToBuffer(oneWhitePixelBuffer);
    oneWhitePixelBitmap.copyPixelsToBuffer(oneWhitePixelBuffer);
    oneWhitePixelBitmap.copyPixelsToBuffer(oneWhitePixelBuffer);
    oneWhitePixelBitmap.copyPixelsToBuffer(oneWhitePixelBuffer);
    oneWhitePixelBuffer.flip();

    /** CREATE THE DESCRIPTOR FROM THE BUFFER **/
    final com.google.android.filament.Texture.PixelBufferDescriptor whitePixBuf =
            new com.google.android.filament.Texture.PixelBufferDescriptor(
                    oneWhitePixelBuffer,
                    Texture.Format.RGB,
                    //Texture.Type.HALF);
                    Texture.Type.UINT_10F_11F_11F_REV);

    /** CREATE THE TEXTURE AND COPY THE DESCRIPTOR **/
    Texture whiteCube = new com.google.android.filament.Texture.Builder()
            .width(1)
            .height(1)
            .levels(1)
            .sampler( Texture.Sampler.SAMPLER_CUBEMAP )
            .format( Texture.InternalFormat.R11F_G11F_B10F )
            .build( engine.getFilamentEngine() );

    /** SET IMAGE IN THE TEXTURE - 6 FACES **/
    whiteCube.setImage(engine.getFilamentEngine(), 0, whitePixBuf,  faceOffsets);

    /** CREATE THE INDIRECT LIGHT FROM THE TEXTURE **/
    IndirectLight whiteCubeIndirectLight = new IndirectLight.Builder()
            .reflections(whiteCube)
            .intensity( 20000.0f )
            .build(EngineInstance.getEngine().getFilamentEngine());

    if (rotation != null) {
      whiteCubeIndirectLight.setRotation(quaternionToRotationMatrix(rotation));
    }

    if (whiteCubeIndirectLight == null) {
      throw new IllegalStateException("Light Probe is invalid.");
    }

    return whiteCubeIndirectLight;
  }
romainguy commented 3 years ago

Your source data is a PNG so your pixels will be ARGB8, you are using the wrong pixel format. You can’t use half nor r11g11b10f. Also why load a PNG if all you’re doing is create a 1x1 white image?

abbana commented 3 years ago

Thanks @romainguy

Your source data is a PNG so your pixels will be ARGB8, you are using the wrong pixel format. You can’t use half nor r11g11b10f.

This is what I have , Format nor Type have ARGB8

    /**
     * Pixel color format
     */
    public enum Format {
        R,
        R_INTEGER,
        RG,
        RG_INTEGER,
        RGB,
        RGB_INTEGER,
        RGBA,
        RGBA_INTEGER,
        UNUSED,
        DEPTH_COMPONENT,
        DEPTH_STENCIL,
        STENCIL_INDEX,
        ALPHA
    }
    /**
     * Pixel data type
     */
    public enum Type {
        /** unsigned byte, 8-bits */
        UBYTE,
        /** signed byte, 8-bits */
        BYTE,
        /** unsigned short, 16-bits */
        USHORT,
        /** signed short, 16-bits */
        SHORT,
        /** unsigned int, 32-bits */
        UINT,
        /** signed int, 32-bits */
        INT,
        /** half-float, 16-bits float with 10 bits mantissa */
        HALF,
        /** float, 32-bits float, with 24 bits mantissa */
        FLOAT,
        /** a compessed type */
        COMPRESSED,
        /** unsigned 5.6 (5.5 for blue) float packed in 32-bits */
        UINT_10F_11F_11F_REV
    }

Also why load a PNG if all you’re doing is create a 1x1 white image? Aim is to set separate image each face on a later time