Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c0cc6db authored by Romain Guy's avatar Romain Guy
Browse files

Add refraction and bettr normals computation to FallRS

parent 4c35e2c5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
    <application android:label="FallRS">

        <activity
            android:screenOrientation="portrait"
            android:name="Fall"
            android:theme="@android:style/Theme.NoTitleBar">

+223 KiB
Loading image diff...
+112 −10
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#define RSID_RIPPLE_INDEX 6
#define RSID_DROP_X 7
#define RSID_DROP_Y 8
#define RSID_RUNNING 9
    
#define RSID_TEXTURES 1

@@ -35,7 +36,7 @@
#define RSID_REFRACTION_MAP 3

#define REFRACTION 1.333f
#define DAMP 4
#define DAMP 3

#define DROP_RADIUS 2
// The higher, the smaller the ripple
@@ -113,6 +114,20 @@ void updateRipples() {
    }
}

int refraction(int d, int wave) {
    int* map = loadArrayI32(RSID_REFRACTION_MAP, 0);
    int i = d;
    if (i < 0) i = -i;
    if (i > 512) i = 512;
    int w = (wave + 0x10000) >> 8;
    w &= ~(w >> 31);
    int r = (map[i] * w) >> 3;
    if (d < 0) {
        return -r;
    }
    return r;
}

void generateRipples() {
    int rippleMapSize = loadI32(RSID_STATE, RSID_RIPPLE_MAP_SIZE);
    int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
@@ -135,6 +150,19 @@ void generateRipples() {
            int dx = nextWave - wave;
            int dy = current[b] - wave;

            int offsetx = refraction(dx, wave) >> 16;
            int u = (width - w) + offsetx;
            u &= ~(u >> 31);
            if (u >= width) u = width - 1;

            int offsety = refraction(dy, wave) >> 16;
            int v = (height - h) + offsety;
            v &= ~(v >> 31);
            if (v >= height) v = height - 1;

            vertices[(offset + w) * 8 + 3] = u / (float) width;
            vertices[(offset + w) * 8 + 4] = v / (float) height;

            // Update Z coordinate of the vertex
            vertices[(offset + w) * 8 + 7] = (dy / 512.0f) / RIPPLE_HEIGHT;
            
@@ -188,9 +216,63 @@ void generateRipples() {
            n3y /= len;
            n3z /= len;
            
            vertices[(yOffset + x) * 8 + 0] = -n3x;
            vertices[(yOffset + x) * 8 + 1] = -n3y;
            // V2
            v2x = vertices[(yOffset + width + x + 1) * 8 + 5];
            v2y = vertices[(yOffset + width + x + 1) * 8 + 6];
            v2z = vertices[(yOffset + width + x + 1) * 8 + 7];

            // N1
            n1x = v2x - v1x;
            n1y = v2y - v1y;
            n1z = v2z - v1z;

            // N2
            n2x = v3x - v1x;
            n2y = v3y - v1y;
            n2z = v3z - v1z;

            // Avegare of previous normal and N1 x N2
            n3x = n3x / 2.0f + (n1y * n2z - n1z * n2y) / 2.0f;
            n3y = n3y / 2.0f + (n1z * n2x - n1x * n2z) / 2.0f;
            n3z = n3z / 2.0f + (n1x * n2y - n1y * n2x) / 2.0f;

            // Normalize
            len = magf3(n3x, n3y, n3z);
            n3x /= len;
            n3y /= len;
            n3z /= len;

            vertices[(yOffset + x) * 8 + 0] = n3x;
            vertices[(yOffset + x) * 8 + 1] = n3y;
            vertices[(yOffset + x) * 8 + 2] = -n3z;
            
            // reset Z
            vertices[(yOffset + x) * 8 + 7] = 0.0f;
        }
    }
}

void drawNormals() {
    int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
    int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);

    float *vertices = loadTriangleMeshVerticesF(NAMED_mesh);
    
    bindProgramVertex(NAMED_PVLines);
    color(1.0f, 0.0f, 0.0f, 1.0f);

    int y = 0;
    for ( ; y < height; y++) {
        int yOffset = y * width;
        int x = 0;
        for ( ; x < width; x++) {
            float vx = vertices[(yOffset + x) * 8 + 5];
            float vy = vertices[(yOffset + x) * 8 + 6];
            float vz = vertices[(yOffset + x) * 8 + 7];
            float nx = vertices[(yOffset + x) * 8 + 0];
            float ny = vertices[(yOffset + x) * 8 + 1];
            float nz = vertices[(yOffset + x) * 8 + 2];
            drawLine(vx, vy, vz, vx + nx / 10.0f, vy + ny / 10.0f, vz + nz / 10.0f);
        }
    }
}
@@ -204,13 +286,33 @@ int main(int index) {
        storeI32(RSID_STATE, RSID_DROP_Y, -1);
    }

    int isRunning = loadI32(RSID_STATE, RSID_RUNNING);
    if (isRunning) {
        updateRipples();
        generateRipples();
        updateTriangleMesh(NAMED_mesh);
    }

    ambient(0.0f, 0.1f, 0.9f, 1.0f);
    diffuse(0.0f, 0.1f, 0.9f, 1.0f);
    bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
    drawTriangleMesh(NAMED_mesh);
    
    ambient(0.0f, 0.0f, 0.0f, 1.0f);
    diffuse(0.0f, 0.0f, 0.0f, 1.0f);
    specular(0.44f, 0.44f, 0.44f, 1.0f);
    shininess(40.0f);
    bindProgramFragment(NAMED_PFLighting);
    drawTriangleMesh(NAMED_mesh);

//    bindProgramVertex(NAMED_PVSky);
//    bindProgramFragment(NAMED_PFSky);
//    bindProgramFragmentStore(NAMED_PFSSky);
//    color(1.0f, 1.0f, 1.0f, 0.30f);
//    bindTexture(NAMED_PFSky, 0, NAMED_TSky);
//    drawTriangleMesh(NAMED_mesh);

    if (!isRunning) {
        drawNormals();
    }

    return 1;
}
+34 −22
Original line number Diff line number Diff line
@@ -33,8 +33,6 @@ import static android.renderscript.ProgramStore.BlendDstFunc;
import static android.renderscript.ProgramStore.BlendSrcFunc;
import static android.renderscript.ProgramFragment.EnvMode.*;
import static android.renderscript.Element.*;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;

import java.util.TimeZone;

@@ -51,17 +49,20 @@ class FallRS {
    private static final int RSID_STATE_RIPPLE_INDEX = 6;
    private static final int RSID_STATE_DROP_X = 7;
    private static final int RSID_STATE_DROP_Y = 8;
    private static final int RSID_STATE_RUNNING = 9;
    
    private static final int RSID_TEXTURES = 1;
    private static final int TEXTURES_COUNT = 0;
    private static final int TEXTURES_COUNT = 1;
    private static final int RSID_TEXTURE_RIVERBED = 0;

    private static final int RSID_RIPPLE_MAP = 2;

    private static final int RSID_REFRACTION_MAP = 3;

    private boolean mIsRunning = true;    
    
    private Resources mResources;
    private RenderScript mRS;
    private final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();

    private final int mWidth;
    private final int mHeight;
@@ -69,8 +70,10 @@ class FallRS {
    private ScriptC mScript;
    private Sampler mSampler;
    private ProgramFragment mPfBackground;
    private ProgramFragment mPfLighting;
    private ProgramStore mPfsBackground;
    private ProgramVertex mPvBackground;
    private ProgramVertex mPvLines;
    private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
    private Light mLight;

@@ -89,8 +92,6 @@ class FallRS {
    public FallRS(int width, int height) {
        mWidth = width;
        mHeight = height;
        mBitmapOptions.inScaled = false;
        mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
    }

    public void init(RenderScript rs, Resources res) {
@@ -116,6 +117,8 @@ class FallRS {
        mLight.destroy();
        mRippleMap.destroy();
        mRefractionMap.destroy();
        mPvLines.destroy();
        mPfLighting.destroy();
    }

    @Override
@@ -177,10 +180,11 @@ class FallRS {
        
        for (int y = 0; y <= hResolution; y++) {
            final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight;
            final float t = 1.0f - y / (float) hResolution;
            for (int x = 0; x <= wResolution; x++) {
                rs.triangleMeshAddVertex_XYZ_ST_NORM(
                        -1.0f + x * quadWidth - quadWidth, yOffset, 0.0f,
                        x / (float) wResolution, y / (float) wResolution,
                        x / (float) wResolution, t,
                        0.0f, 0.0f, -1.0f);
            }
        }
@@ -204,7 +208,7 @@ class FallRS {
    private void createScriptStructures() {
        final int rippleMapSize = (mMeshWidth + 2) * (mMeshHeight + 2);

        final int[] data = new int[9];
        final int[] data = new int[10];
        mState = Allocation.createSized(mRS, USER_I32, data.length);
        data[RSID_STATE_FRAMECOUNT] = 0;
        data[RSID_STATE_WIDTH] = mWidth;
@@ -215,6 +219,7 @@ class FallRS {
        data[RSID_STATE_RIPPLE_INDEX] = 0;
        data[RSID_STATE_DROP_X] = mMeshWidth / 2;
        data[RSID_STATE_DROP_Y] = mMeshHeight / 2;
        data[RSID_STATE_RUNNING] = 1;
        mState.data(data);

        final int[] rippleMap = new int[rippleMapSize * 2];
@@ -236,7 +241,7 @@ class FallRS {
        mTexturesIDs = Allocation.createSized(mRS, USER_FLOAT, TEXTURES_COUNT);

        final Allocation[] textures = mTextures;
        // TOOD: Load textures
        textures[RSID_TEXTURE_RIVERBED] = loadTexture(R.drawable.riverbed, "TRiverbed");

        final int[] bufferIds = mTextureBufferIDs;
        final int count = textures.length;
@@ -257,15 +262,6 @@ class FallRS {
        return allocation;
    }

    private Allocation loadTextureARGB(int id, String name) {
        // Forces ARGB 32 bits, because pngcrush sometimes optimize our PNGs to
        // indexed pictures, which are not well supported
        final Bitmap b = BitmapFactory.decodeResource(mResources, id, mBitmapOptions);
        final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888, false);
        allocation.setName(name);
        return allocation;
    }

    private void createProgramFragment() {
        Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
        sampleBuilder.setMin(LINEAR);
@@ -280,12 +276,18 @@ class FallRS {
        mPfBackground = builder.create();
        mPfBackground.setName("PFBackground");
        mPfBackground.bindSampler(mSampler, 0);
        
        builder = new ProgramFragment.Builder(mRS, null, null);
        builder.setTexEnable(false, 0);
        mPfLighting = builder.create();
        mPfLighting.setName("PFLighting");
        mPfLighting.bindSampler(mSampler, 0);
    }

    private void createProgramFragmentStore() {
        ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
        builder.setDepthFunc(LESS);
        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
        builder.setDepthFunc(ALWAYS);
        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
        builder.setDitherEnable(true);
        builder.setDepthMask(true);
        mPfsBackground = builder.create();
@@ -297,7 +299,7 @@ class FallRS {
        mPvOrthoAlloc.setupProjectionNormalized(mWidth, mHeight);

        mLight = new Light.Builder(mRS).create();
        mLight.setPosition(0.0f, 0.0f, -1.0f);
        mLight.setPosition(0.0f, 2.0f, -8.0f);

        ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
        builder.setTextureMatrixEnable(true);
@@ -305,11 +307,21 @@ class FallRS {
        mPvBackground = builder.create();
        mPvBackground.bindAllocation(mPvOrthoAlloc);
        mPvBackground.setName("PVBackground");
        
        builder = new ProgramVertex.Builder(mRS, null, null);
        mPvLines = builder.create();
        mPvLines.bindAllocation(mPvOrthoAlloc);
        mPvLines.setName("PVLines");
    }

    public void addDrop(float x, float y) {
    void addDrop(float x, float y) {
        mState.subData1D(RSID_STATE_DROP_X, 2, new int[] {
                (int) ((x / mWidth) * mMeshWidth), (int) ((y / mHeight) * mMeshHeight)
        });
    }
    
    void togglePause() {
        mIsRunning = !mIsRunning;
        mState.subData1D(RSID_STATE_RUNNING, 1, new int[] { mIsRunning ? 1 : 0 });
    }
}
+12 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package com.android.fall.rs;
import android.content.Context;
import android.view.SurfaceHolder;
import android.view.MotionEvent;
import android.view.KeyEvent;
import android.renderscript.RenderScript;
import android.renderscript.RSSurfaceView;

@@ -28,6 +29,8 @@ class FallView extends RSSurfaceView {

    public FallView(Context context) {
        super(context);
        setFocusable(true);
        setFocusableInTouchMode(true);
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
@@ -43,6 +46,15 @@ class FallView extends RSSurfaceView {
        if (mRender != null) mRender.destroy();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER ||
                keyCode == KeyEvent.KEYCODE_MENU) {
            mRender.togglePause();
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
Loading