문제

I need to pass LUT from Android application to the fragment shader for color correction. I've found some examples where LUT is passed as Bitmap

GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, name);
...
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.raw.brick1);
GLUtils.texImage2D(GLES20.GL_TEXTURE_CUBE_MAP, 0, bitmap, 0);

But what to do if my LUT is not 3D image file and is not built with series of texture2D maps? My LUT is a float[] array. How I can bind it with uniform samplerCube in my fragment shader?

도움이 되었습니까?

해결책

Short answer is "It's not possible do directly via OpenGL shader, but possible via renderscript" More details about "shader" approach: Fragment shader code is bellow. Pay attention the 1 line must be defined to use texture3D

#extension GL_OES_texture_3D : enable 
precision mediump float;
uniform sampler2D u_texture0;
uniform vec4 uColor;
varying vec4 v_vertex;
uniform sampler3D u_lut;
void main() {
    vec2 texcoord0 = v_vertex.xy;
    vec4 rawColor=texture2D(u_texture0, texcoord0);
    vec4 outColor = texture3D(u_lut, rawColor.rgb);
    gl_FragColor = outColor; //rawColor;
}

java code:

FloatBuffer texBuffer = ByteBuffer.allocateDirect(array.length * Float.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, iAxisSize, iAxisSize, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, texBuffer);

It works without compile or run time error but as result you'll see black screen. Sure you must use glTexImage3D function instead glTexImage2D, BUT it's not implemented in android SDK17 and you can't do anything with it.

The good news: in Android SDK17 implemented ScriptIntrinsicLUT that can be used to apply 1D LUT to source image. Java code is bellow:

private RenderScript mRS;
private Allocation mInAllocation;
private Allocation mOutAllocation;
private ScriptC_mono mScript;
private ScriptIntrinsicLUT mIntrinsic;
...
mRS = RenderScript.create(this);
mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS) );
createLUT();
mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
                                                Allocation.MipmapControl.MIPMAP_NONE,
                                                Allocation.USAGE_SCRIPT);
mOutAllocation = Allocation.createTyped(mRS, mInAllocation.getType());
mIntrinsic.forEach(mInAllocation, mOutAllocation);
mOutAllocation.copyTo(mBitmapOut);
...
private void createLUT() {
    for (int ct=0; ct < 256; ct++) {
        float f = ((float)ct) / 255.f;

        float r = f;
        if (r < 0.5f) {
            r = 4.0f * r * r * r;
        } else {
            r = 1.0f - r;
            r = 1.0f - (4.0f * r * r * r);
        }
        mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));

        float g = f;
        if (g < 0.5f) {
            g = 2.0f * g * g;
        } else {
            g = 1.0f - g;
            g = 1.0f - (2.0f * g * g);
        }
        mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));

        float b = f * 0.5f + 0.25f;
        mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
    }
}

More details about: http://developer.android.com/reference/android/renderscript/ScriptIntrinsicLUT.html http://my.fit.edu/~vkepuska/ece5570/adt-bundle-windows-x86_64/sdk/sources/android-17/com/android/rs/image/CrossProcess.java

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top