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

Commit ecc7ca03 authored by Romain Guy's avatar Romain Guy
Browse files

Add swaying effect to the grass.

parent 8031361a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ LOCAL_SRC_FILES:= \
	rsObjectBase.cpp \
	rsMatrix.cpp \
        rsMesh.cpp \
	rsNoise.cpp \
	rsProgram.cpp \
	rsProgramFragment.cpp \
	rsProgramFragmentStore.cpp \
+56 −54
Original line number Diff line number Diff line
@@ -17,12 +17,11 @@
#pragma stateFragment(PFBackground)
#pragma stateFragmentStore(PFSBackground)

#define WVGA_PORTRAIT_WIDTH 480.0f
#define WVGA_PORTRAIT_HEIGHT 762.0f

#define RSID_STATE 0
#define RSID_FRAME_COUNT 0
#define RSID_BLADES_COUNT 1
#define RSID_WIDTH 2
#define RSID_HEIGHT 3

#define RSID_TEXTURES 1
#define RSID_SKY_TEXTURE_NIGHT 0
@@ -33,7 +32,7 @@

#define RSID_BLADES 2
#define BLADE_STRUCT_FIELDS_COUNT 12
#define BLADE_STRUCT_DEGREE 0
#define BLADE_STRUCT_ANGLE 0
#define BLADE_STRUCT_SIZE 1
#define BLADE_STRUCT_XPOS 2
#define BLADE_STRUCT_YPOS 3
@@ -46,7 +45,9 @@
#define BLADE_STRUCT_S 10
#define BLADE_STRUCT_B 11

#define TESSELATION 4.0f
#define TESSELATION 2.0f

#define MAX_BEND 0.09f

#define MIDNIGHT 0.0f
#define MORNING 0.375f
@@ -70,31 +71,30 @@ void alpha(float a) {
    color(1.0f, 1.0f, 1.0f, a);
}

void drawNight() {
void drawNight(int width, int height) {
    bindTexture(NAMED_PFBackground, 0, loadI32(RSID_TEXTURES, RSID_SKY_TEXTURE_NIGHT));
    // NOTE: Hacky way to draw the night sky
    drawRect(WVGA_PORTRAIT_WIDTH - 512.0f, -32.0f, WVGA_PORTRAIT_WIDTH, 1024.0f - 32.0f, 0.0f);
    drawRect(width - 512.0f, -32.0f, width, 1024.0f - 32.0f, 0.0f);
}

void drawSunrise() {
void drawSunrise(int width, int height) {
    bindTexture(NAMED_PFBackground, 0, loadI32(RSID_TEXTURES, RSID_SKY_TEXTURE_SUNRISE));
    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
    drawRect(0.0f, 0.0f, width, height, 0.0f);
}

void drawNoon() {
void drawNoon(int width, int height) {
    bindTexture(NAMED_PFBackground, 0, loadI32(RSID_TEXTURES, RSID_SKY_TEXTURE_NOON));
    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
    drawRect(0.0f, 0.0f, width, height, 0.0f);
}

void drawSunset() {
void drawSunset(int width, int height) {
    bindTexture(NAMED_PFBackground, 0, loadI32(RSID_TEXTURES, RSID_SKY_TEXTURE_SUNSET));
    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
    drawRect(0.0f, 0.0f, width, height, 0.0f);
}

void drawBlade(int index, float now) {
void drawBlade(int index, float now, int frameCount) {
    float offset = loadF(RSID_BLADES, index + BLADE_STRUCT_OFFSET);
    float scale = loadF(RSID_BLADES, index + BLADE_STRUCT_SCALE);
    float degree = loadF(RSID_BLADES, index + BLADE_STRUCT_DEGREE);
    float angle = loadF(RSID_BLADES, index + BLADE_STRUCT_ANGLE);
    float hardness = loadF(RSID_BLADES, index + BLADE_STRUCT_HARDNESS);
    
    float xpos = loadF(RSID_BLADES, index + BLADE_STRUCT_XPOS);
@@ -124,38 +124,43 @@ void drawBlade(int index, float now) {

    hsb(h, s, lerpf(0, b, newB), 1.0f);

    float targetDegree = 0.0f; // TODO Compute
    degree += (targetDegree - degree) * 0.3f;
    float newAngle = turbulencef2(xpos * 0.006f, frameCount * 0.006f, 4.0f) - 0.5f;
    newAngle /= 2.0f;
    angle = clampf(angle + (newAngle + offset - angle) * 0.15f, -MAX_BEND, MAX_BEND);

    float angle = PI / 2.0f;
    float currentAngle = PI / 2.0f;

    float currentX = xpos;
    float currentY = ypos;
    float bottomX = xpos;
    float bottomY = ypos;

    int i = size * TESSELATION;
    float lx = lengthX / TESSELATION;
    float ly = lengthY / TESSELATION;
    float ss = 2.0f / i + scale / TESSELATION;
    float sh = 0.7f / TESSELATION;
    float ss = 4.0f / i + scale / TESSELATION;
    float sh = 0.5f / TESSELATION;
    float d = angle * hardness / TESSELATION;

    for ( ; i > 0; i--) {
        float nextX = currentX - cosf(angle) * size * lx;
        float nextY = currentY - sinf(angle) * size * ly;
        angle += degree * hardness;
        float topX = bottomX - cosf(currentAngle) * size * lx;
        float topY = bottomY - sinf(currentAngle) * size * ly;
        currentAngle += d;

        float spi = (i - 1) * ss;
        float si = i * ss;

        drawQuad(nextX + (i - 1) * ss, nextY, 0.0f,
                 nextX - (i - 1) * ss, nextY, 0.0f,
                 currentX - i * ss, currentY + sh, 0.0f,
                 currentX + i * ss, currentY + sh, 0.0f);
        drawQuad(topX + spi, topY, 0.0f,
                 topX - spi, topY, 0.0f,
                 bottomX - si, bottomY + sh, 0.0f,
                 bottomX + si, bottomY + sh, 0.0f);

        currentX = nextX;
        currentY = nextY;
        bottomX = topX;
        bottomY = topY;
    }

    storeF(RSID_BLADES, index + BLADE_STRUCT_DEGREE, degree);
    storeF(RSID_BLADES, index + BLADE_STRUCT_ANGLE, angle);
}

void drawBlades(float now) {
void drawBlades(float now, int frameCount) {
    // For anti-aliasing
    bindProgramFragmentStore(NAMED_PFSGrass);
    bindProgramFragment(NAMED_PFGrass);
@@ -166,40 +171,37 @@ void drawBlades(float now) {

    int i = 0;
    for ( ; i < count; i += BLADE_STRUCT_FIELDS_COUNT) {
        drawBlade(i, now);
        drawBlade(i, now, frameCount);
    }
}

int main(int launchID) {
    int width = loadI32(RSID_STATE, RSID_WIDTH);
    int height = loadI32(RSID_STATE, RSID_HEIGHT);

    int frameCount = loadI32(RSID_STATE, RSID_FRAME_COUNT);
    float now = time(frameCount);
    alpha(1.0f);

    if (now >= MIDNIGHT && now < MORNING) {
        drawNight();
        drawNight(width, height);
        alpha(normf(MIDNIGHT, MORNING, now));
        drawSunrise();
    }
    
    if (now >= MORNING && now < AFTERNOON) {
        drawSunrise();
        drawSunrise(width, height);
    } else if (now >= MORNING && now < AFTERNOON) {
        drawSunrise(width, height);
        alpha(normf(MORNING, AFTERNOON, now));
        drawNoon();
    }

    if (now >= AFTERNOON && now < DUSK) {
        drawNoon();
        drawNoon(width, height);
    } else if (now >= AFTERNOON && now < DUSK) {
        drawNoon(width, height);
        alpha(normf(AFTERNOON, DUSK, now));
        drawSunset();
    }
    
    if (now >= DUSK) {
        drawNight();
        drawSunset(width, height);
    } else if (now >= DUSK) {
        drawNight(width, height);
        alpha(1.0f - normf(DUSK, 1.0f, now));
        drawSunset();
        drawSunset(width, height);
    }

    drawBlades(now);
    drawBlades(now, frameCount);

    frameCount++;
    storeI32(RSID_STATE, RSID_FRAME_COUNT, frameCount);
+7 −3
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ class GrassRS {
    private static final int RSID_STATE = 0;
    private static final int RSID_STATE_FRAMECOUNT = 0;
    private static final int RSID_STATE_BLADES_COUNT = 1;
    private static final int RSID_STATE_WIDTH = 2;
    private static final int RSID_STATE_HEIGHT = 3;

    private static final int RSID_SKY_TEXTURES = 1;
    private static final int SKY_TEXTURES_COUNT = 5;
@@ -46,7 +48,7 @@ class GrassRS {
    private static final int RSID_BLADES = 2;
    private static final int BLADES_COUNT = 100;
    private static final int BLADE_STRUCT_FIELDS_COUNT = 12;
    private static final int BLADE_STRUCT_DEGREE = 0;
    private static final int BLADE_STRUCT_ANGLE = 0;
    private static final int BLADE_STRUCT_SIZE = 1;
    private static final int BLADE_STRUCT_XPOS = 2;
    private static final int BLADE_STRUCT_YPOS = 3;
@@ -129,10 +131,12 @@ class GrassRS {
    }

    private void createScriptStructures() {
        final int[] data = new int[2];
        final int[] data = new int[4];
        mState = Allocation.createSized(mRS, USER_I32, data.length);
        data[RSID_STATE_FRAMECOUNT] = 0;
        data[RSID_STATE_BLADES_COUNT] = BLADES_COUNT;
        data[RSID_STATE_WIDTH] = mWidth;
        data[RSID_STATE_HEIGHT] = mHeight;
        mState.data(data);

        final float[] blades = new float[BLADES_COUNT * BLADE_STRUCT_FIELDS_COUNT];
@@ -145,7 +149,7 @@ class GrassRS {

    private void createBlade(float[] blades, int index) {
        //noinspection PointlessArithmeticExpression
        blades[index + BLADE_STRUCT_DEGREE] = 0.0f;
        blades[index + BLADE_STRUCT_ANGLE] = 0.0f;
        blades[index + BLADE_STRUCT_SIZE] = random(4.0f) + 4.0f;
        blades[index + BLADE_STRUCT_XPOS] = random(mWidth);
        blades[index + BLADE_STRUCT_YPOS] = mHeight;

libs/rs/rsNoise.cpp

0 → 100644
+256 −0
Original line number Diff line number Diff line
/*
 * This implementation of the noise functions was ported from the Java
 * implementation by Jerry Huxtable (http://www.jhlabs.com) under
 * Apache License 2.0 (see http://jhlabs.com/ip/filters/download.html)
 *
 * Original header:
 *
 * Copyright 2006 Jerry Huxtable
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "rsNoise.h"

#include <math.h>
#include <stdlib.h>
#include <time.h>

namespace android {
namespace renderscript {

#define B 0x100
#define BM 0xff
#define N 0x1000

static int p[B + B + 2];
static float g3[B + B + 2][3];
static float g2[B + B + 2][2];
static float g1[B + B + 2];
static bool noise_start = true;

#define lerpf(start, stop, amount) start + (stop - start) * amount

static inline float noise_sCurve(float t)
{
    return t * t * (3.0f - 2.0f * t);
}

inline void SC_normalizef2(float v[])
{
    float s = (float)sqrtf(v[0] * v[0] + v[1] * v[1]);
    v[0] = v[0] / s;
    v[1] = v[1] / s;
}

inline void SC_normalizef3(float v[])
{
    float s = (float)sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
    v[0] = v[0] / s;
    v[1] = v[1] / s;
    v[2] = v[2] / s;
}

static void noise_init()
{
    int i, j, k;
    
    for (i = 0; i < B; i++) {
        p[i] = i;
        
        g1[i] = (float)((rand() % (B + B)) - B) / B;
        
        for (j = 0; j < 2; j++)
            g2[i][j] = (float)((rand() % (B + B)) - B) / B;
        SC_normalizef2(g2[i]);
        
        for (j = 0; j < 3; j++)
            g3[i][j] = (float)((rand() % (B + B)) - B) / B;
        SC_normalizef3(g3[i]);
    }
    
    for (i = B-1; i >= 0; i--) {
        k = p[i];
        p[i] = p[j = rand() % B];
        p[j] = k;
    }
    
    for (i = 0; i < B + 2; i++) {
        p[B + i] = p[i];
        g1[B + i] = g1[i];
        for (j = 0; j < 2; j++)
            g2[B + i][j] = g2[i][j];
        for (j = 0; j < 3; j++)
            g3[B + i][j] = g3[i][j];
    }
}

float SC_noisef(float x)
{
    srand(time(NULL));
    int bx0, bx1;
    float rx0, rx1, sx, t, u, v;
    
    if (noise_start) {
        noise_start = false;
        noise_init();
    }
    
    t = x + N;
    bx0 = ((int)t) & BM;
    bx1 = (bx0+1) & BM;
    rx0 = t - (int)t;
    rx1 = rx0 - 1.0f;
    
    sx = noise_sCurve(rx0);
    
    u = rx0 * g1[p[bx0]];
    v = rx1 * g1[p[bx1]];
    return 2.3f * lerpf(u, v, sx);
}

float SC_noisef2(float x, float y)
{
    srand(time(NULL));
    int bx0, bx1, by0, by1, b00, b10, b01, b11;
    float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v;
    float *q;
    int i, j;
    
    if (noise_start) {
        noise_start = false;
        noise_init();
    }
    
    t = x + N;
    bx0 = ((int)t) & BM;
    bx1 = (bx0+1) & BM;
    rx0 = t - (int)t;
    rx1 = rx0 - 1.0f;
	
    t = y + N;
    by0 = ((int)t) & BM;
    by1 = (by0+1) & BM;
    ry0 = t - (int)t;
    ry1 = ry0 - 1.0f;
	
    i = p[bx0];
    j = p[bx1];
    
    b00 = p[i + by0];
    b10 = p[j + by0];
    b01 = p[i + by1];
    b11 = p[j + by1];
    
    sx = noise_sCurve(rx0);
    sy = noise_sCurve(ry0);
    
    q = g2[b00]; u = rx0 * q[0] + ry0 * q[1];
    q = g2[b10]; v = rx1 * q[0] + ry0 * q[1];
    a = lerpf(u, v, sx);
    
    q = g2[b01]; u = rx0 * q[0] + ry1 * q[1];
    q = g2[b11]; v = rx1 * q[0] + ry1 * q[1];
    b = lerpf(u, v, sx);
    
    return 1.5f*lerpf(a, b, sy);
}

float SC_noisef3(float x, float y, float z)
{
    srand(time(NULL));
    int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
    float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
    float *q;
    int i, j;
    
    if (noise_start) {
        noise_start = false;
        noise_init();
    }
    
    t = x + N;
    bx0 = ((int)t) & BM;
    bx1 = (bx0+1) & BM;
    rx0 = t - (int)t;
    rx1 = rx0 - 1.0f;
    
    t = y + N;
    by0 = ((int)t) & BM;
    by1 = (by0+1) & BM;
    ry0 = t - (int)t;
    ry1 = ry0 - 1.0f;
	
    t = z + N;
    bz0 = ((int)t) & BM;
    bz1 = (bz0+1) & BM;
    rz0 = t - (int)t;
    rz1 = rz0 - 1.0f;
	
    i = p[bx0];
    j = p[bx1];
    
    b00 = p[i + by0];
    b10 = p[j + by0];
    b01 = p[i + by1];
    b11 = p[j + by1];
    
    t  = noise_sCurve(rx0);
    sy = noise_sCurve(ry0);
    sz = noise_sCurve(rz0);
    
    q = g3[b00 + bz0]; u = rx0 * q[0] + ry0 * q[1] + rz0 * q[2];
    q = g3[b10 + bz0]; v = rx1 * q[0] + ry0 * q[1] + rz0 * q[2];
    a = lerpf(u, v, t);
    
    q = g3[b01 + bz0]; u = rx0 * q[0] + ry1 * q[1] + rz0 * q[2];
    q = g3[b11 + bz0]; v = rx1 * q[0] + ry1 * q[1] + rz0 * q[2];
    b = lerpf(u, v, t);
    
    c = lerpf(a, b, sy);
    
    q = g3[b00 + bz1]; u = rx0 * q[0] + ry0 * q[1] + rz1 * q[2];
    q = g3[b10 + bz1]; v = rx1 * q[0] + ry0 * q[1] + rz1 * q[2];
    a = lerpf(u, v, t);
    
    q = g3[b01 + bz1]; u = rx0 * q[0] + ry1 * q[1] + rz1 * q[2];
    q = g3[b11 + bz1]; v = rx1 * q[0] + ry1 * q[1] + rz1 * q[2];
    b = lerpf(u, v, t);
    
    d = lerpf(a, b, sy);
    
    return 1.5f*lerpf(c, d, sz);
}

float SC_turbulencef2(float x, float y, float octaves)
{
    srand(time(NULL));
    float t = 0.0f;
    
    for (float f = 1.0f; f <= octaves; f *= 2)
        t += fabs(SC_noisef2(f * x, f * y)) / f;
    return t;
}

float SC_turbulencef3(float x, float y, float z, float octaves)
{
    srand(time(NULL));
    float t = 0.0f;
    
    for (float f = 1.0f; f <= octaves; f *= 2)
        t += fabs(SC_noisef3(f * x, f * y, f * z)) / f;
    return t;
}

}
}
 No newline at end of file

libs/rs/rsNoise.h

0 → 100644
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_RS_NOISE_H
#define ANDROID_RS_NOISE_H

// ---------------------------------------------------------------------------
namespace android {
namespace renderscript {

void SC_normalizef2(float v[]);
void SC_normalizef3(float v[]);
float SC_noisef(float x);
float SC_noisef2(float x, float y);
float SC_noisef3(float x, float y, float z);
float SC_turbulencef2(float x, float y, float octaves);
float SC_turbulencef3(float x, float y, float z, float octaves);

}
}

#endif
Loading