如何在Andengine中制作流水效果?
How to make water effect in Andengine?
萨拉姆
我想用 AndEngine 为 android 设计动态壁纸,
我想要水波纹效果。我怎样才能做到这一点?
喜欢 this.
这就是它在 GLES2 上的工作方式。
着色器延伸到整个屏幕。您需要针对自定义半径对其进行调整。
这段代码进入主class/activity:
private float mShockwaveTime = 0f;
@Override
public Engine onCreateEngine(final EngineOptions pEngineOptions) {
return new Engine(pEngineOptions) {
private boolean mRenderTextureInitialized;
private RenderTexture mRenderTexture;
private UncoloredSprite mRenderTextureSprite;
@Override
public void onDrawFrame(GLState pGLState)
throws InterruptedException {
if (mShockwaveTime > 0f && mShockwaveTime < 10f) {
if (!mRenderTextureInitialized) {
initRenderTexture(pGLState);
mRenderTextureInitialized = true;
}
mRenderTexture.begin(pGLState, false, true, Color.TRANSPARENT);
{
super.onDrawFrame(pGLState);
}
mRenderTexture.end(pGLState);
pGLState.pushProjectionGLMatrix();
pGLState.orthoProjectionGLMatrixf(0, CAMERA_WIDTH, 0, CAMERA_HEIGHT, -1, 1);
{
mRenderTextureSprite.onDraw(pGLState, mCamera);
}
pGLState.popProjectionGLMatrix();
} else {
super.onDrawFrame(pGLState);
}
}
private void initRenderTexture(GLState pGLState) {
mRenderTexture = new RenderTexture(getTextureManager(), mCamera.getSurfaceWidth(), mCamera.getSurfaceHeight(), PixelFormat.RGBA_4444);
mRenderTexture.init(pGLState);
mRenderTextureSprite = new UncoloredSprite(0f, 0f, TextureRegionFactory.extractFromTexture(mRenderTexture), getVertexBufferObjectManager()) {
@Override
protected void preDraw(GLState pGLState, Camera pCamera) {
super.preDraw(pGLState, pCamera);
if (mShockwaveTime > 0f && mShockwaveTime < 10f) GLES20.glUniform1f(ShockwaveShaderProgram.sUniformTimeLocation, mShockwaveTime);
}
};
mRenderTextureSprite.setShaderProgram(ShockwaveShaderProgram.getInstance());
}
};
}
这一行在 onLoadResources 中:
this.getShaderProgramManager().loadShaderProgram(ShockwaveShaderProgram.getInstance());
I put shader class code to the end of my main class:
public static class ShockwaveShaderProgram extends ShaderProgram {
private static ShockwaveShaderProgram instance;
public static ShockwaveShaderProgram getInstance() {
if (instance == null) instance = new ShockwaveShaderProgram();
return instance;
}
public static final String FRAGMENTSHADER =
"precision lowp float;\n" +
"uniform lowp sampler2D " + ShaderProgramConstants.UNIFORM_TEXTURE_0 + ";\n" +
"varying mediump vec2 " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" +
"uniform vec2 center;\n" +
"uniform float time;\n" +
"const vec3 params = vec3(10.0, 0.8, 0.02);\n" +
"void main() \n" +
"{ \n" +
" mediump vec2 texCoord = " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" +
" float distance = distance(texCoord, center);\n" +
" if ( (distance <= (time + params.z)) && (distance >= (time - params.z)) )\n" +
" {\n" +
" float diff = (distance - time);\n" +
" float powDiff = 1.0 - pow(abs(diff*params.x), params.y);\n" +
" float diffTime = diff * powDiff;\n" +
" vec2 diffUV = normalize(texCoord - center);\n" +
" texCoord = texCoord + (diffUV * diffTime);\n" +
" }\n" +
" gl_FragColor = texture2D(" + ShaderProgramConstants.UNIFORM_TEXTURE_0 + ", texCoord);\n" +
"} \n";
private ShockwaveShaderProgram() {
super(PositionTextureCoordinatesShaderProgram.VERTEXSHADER, FRAGMENTSHADER);
}
public static int sUniformModelViewPositionMatrixLocation = ShaderProgramConstants.LOCATION_INVALID;
public static int sUniformTexture0Location = ShaderProgramConstants.LOCATION_INVALID;
public static int sUniformCenterLocation = ShaderProgramConstants.LOCATION_INVALID;
public static int sUniformTimeLocation = ShaderProgramConstants.LOCATION_INVALID;
@Override
protected void link(final GLState pGLState) throws ShaderProgramLinkException {
GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_POSITION_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION);
GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES_LOCATION, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES);
super.link(pGLState);
ShockwaveShaderProgram.sUniformModelViewPositionMatrixLocation = this.getUniformLocation(ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX);
ShockwaveShaderProgram.sUniformTexture0Location = this.getUniformLocation(ShaderProgramConstants.UNIFORM_TEXTURE_0);
ShockwaveShaderProgram.sUniformCenterLocation = this.getUniformLocation("center");
ShockwaveShaderProgram.sUniformTimeLocation = this.getUniformLocation("time");
}
@Override
public void bind(final GLState pGLState, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
GLES20.glDisableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION);
super.bind(pGLState, pVertexBufferObjectAttributes);
GLES20.glUniformMatrix4fv(ShockwaveShaderProgram.sUniformModelViewPositionMatrixLocation, 1, false, pGLState.getModelViewProjectionGLMatrix(), 0);
GLES20.glUniform1i(ShockwaveShaderProgram.sUniformTexture0Location, 0);
GLES20.glUniform2f(ShockwaveShaderProgram.sUniformCenterLocation, 0.5f, 0.5f);
}
@Override
public void unbind(final GLState pGLState) throws ShaderProgramException {
GLES20.glEnableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION);
super.unbind(pGLState);
}
}
把这段代码放在你想触发它的地方:
mScene.registerUpdateHandler(new TimerHandler(0.08f, true, new ITimerCallback() {
@Override
public void onTimePassed(TimerHandler pTimerHandler) {
mShockwaveTime += 0.02f;
if (mShockwaveTime > 1.2f) {
mScene.unregisterUpdateHandler(pTimerHandler);
mShockwaveTime = 0.0f;
}
}
}));
萨拉姆
我想用 AndEngine 为 android 设计动态壁纸,
我想要水波纹效果。我怎样才能做到这一点?
喜欢 this.
这就是它在 GLES2 上的工作方式。 着色器延伸到整个屏幕。您需要针对自定义半径对其进行调整。
这段代码进入主class/activity:
private float mShockwaveTime = 0f;
@Override
public Engine onCreateEngine(final EngineOptions pEngineOptions) {
return new Engine(pEngineOptions) {
private boolean mRenderTextureInitialized;
private RenderTexture mRenderTexture;
private UncoloredSprite mRenderTextureSprite;
@Override
public void onDrawFrame(GLState pGLState)
throws InterruptedException {
if (mShockwaveTime > 0f && mShockwaveTime < 10f) {
if (!mRenderTextureInitialized) {
initRenderTexture(pGLState);
mRenderTextureInitialized = true;
}
mRenderTexture.begin(pGLState, false, true, Color.TRANSPARENT);
{
super.onDrawFrame(pGLState);
}
mRenderTexture.end(pGLState);
pGLState.pushProjectionGLMatrix();
pGLState.orthoProjectionGLMatrixf(0, CAMERA_WIDTH, 0, CAMERA_HEIGHT, -1, 1);
{
mRenderTextureSprite.onDraw(pGLState, mCamera);
}
pGLState.popProjectionGLMatrix();
} else {
super.onDrawFrame(pGLState);
}
}
private void initRenderTexture(GLState pGLState) {
mRenderTexture = new RenderTexture(getTextureManager(), mCamera.getSurfaceWidth(), mCamera.getSurfaceHeight(), PixelFormat.RGBA_4444);
mRenderTexture.init(pGLState);
mRenderTextureSprite = new UncoloredSprite(0f, 0f, TextureRegionFactory.extractFromTexture(mRenderTexture), getVertexBufferObjectManager()) {
@Override
protected void preDraw(GLState pGLState, Camera pCamera) {
super.preDraw(pGLState, pCamera);
if (mShockwaveTime > 0f && mShockwaveTime < 10f) GLES20.glUniform1f(ShockwaveShaderProgram.sUniformTimeLocation, mShockwaveTime);
}
};
mRenderTextureSprite.setShaderProgram(ShockwaveShaderProgram.getInstance());
}
};
}
这一行在 onLoadResources 中:
this.getShaderProgramManager().loadShaderProgram(ShockwaveShaderProgram.getInstance());
I put shader class code to the end of my main class:
public static class ShockwaveShaderProgram extends ShaderProgram {
private static ShockwaveShaderProgram instance;
public static ShockwaveShaderProgram getInstance() {
if (instance == null) instance = new ShockwaveShaderProgram();
return instance;
}
public static final String FRAGMENTSHADER =
"precision lowp float;\n" +
"uniform lowp sampler2D " + ShaderProgramConstants.UNIFORM_TEXTURE_0 + ";\n" +
"varying mediump vec2 " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" +
"uniform vec2 center;\n" +
"uniform float time;\n" +
"const vec3 params = vec3(10.0, 0.8, 0.02);\n" +
"void main() \n" +
"{ \n" +
" mediump vec2 texCoord = " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" +
" float distance = distance(texCoord, center);\n" +
" if ( (distance <= (time + params.z)) && (distance >= (time - params.z)) )\n" +
" {\n" +
" float diff = (distance - time);\n" +
" float powDiff = 1.0 - pow(abs(diff*params.x), params.y);\n" +
" float diffTime = diff * powDiff;\n" +
" vec2 diffUV = normalize(texCoord - center);\n" +
" texCoord = texCoord + (diffUV * diffTime);\n" +
" }\n" +
" gl_FragColor = texture2D(" + ShaderProgramConstants.UNIFORM_TEXTURE_0 + ", texCoord);\n" +
"} \n";
private ShockwaveShaderProgram() {
super(PositionTextureCoordinatesShaderProgram.VERTEXSHADER, FRAGMENTSHADER);
}
public static int sUniformModelViewPositionMatrixLocation = ShaderProgramConstants.LOCATION_INVALID;
public static int sUniformTexture0Location = ShaderProgramConstants.LOCATION_INVALID;
public static int sUniformCenterLocation = ShaderProgramConstants.LOCATION_INVALID;
public static int sUniformTimeLocation = ShaderProgramConstants.LOCATION_INVALID;
@Override
protected void link(final GLState pGLState) throws ShaderProgramLinkException {
GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_POSITION_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION);
GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES_LOCATION, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES);
super.link(pGLState);
ShockwaveShaderProgram.sUniformModelViewPositionMatrixLocation = this.getUniformLocation(ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX);
ShockwaveShaderProgram.sUniformTexture0Location = this.getUniformLocation(ShaderProgramConstants.UNIFORM_TEXTURE_0);
ShockwaveShaderProgram.sUniformCenterLocation = this.getUniformLocation("center");
ShockwaveShaderProgram.sUniformTimeLocation = this.getUniformLocation("time");
}
@Override
public void bind(final GLState pGLState, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
GLES20.glDisableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION);
super.bind(pGLState, pVertexBufferObjectAttributes);
GLES20.glUniformMatrix4fv(ShockwaveShaderProgram.sUniformModelViewPositionMatrixLocation, 1, false, pGLState.getModelViewProjectionGLMatrix(), 0);
GLES20.glUniform1i(ShockwaveShaderProgram.sUniformTexture0Location, 0);
GLES20.glUniform2f(ShockwaveShaderProgram.sUniformCenterLocation, 0.5f, 0.5f);
}
@Override
public void unbind(final GLState pGLState) throws ShaderProgramException {
GLES20.glEnableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION);
super.unbind(pGLState);
}
}
把这段代码放在你想触发它的地方:
mScene.registerUpdateHandler(new TimerHandler(0.08f, true, new ITimerCallback() {
@Override
public void onTimePassed(TimerHandler pTimerHandler) {
mShockwaveTime += 0.02f;
if (mShockwaveTime > 1.2f) {
mScene.unregisterUpdateHandler(pTimerHandler);
mShockwaveTime = 0.0f;
}
}
}));