Revision c5369f1b
Added by Leszek Koltunski almost 9 years ago
| src/main/java/org/distorted/library/DistortedEffects.java | ||
|---|---|---|
| 183 | 183 |
// DEBUG ONLY |
| 184 | 184 |
|
| 185 | 185 |
@SuppressWarnings("unused")
|
| 186 |
private void displayBoundingRect(float halfX, float halfY, float halfZ, DistortedFramebuffer df, float[] mvp, float[] vertices)
|
|
| 186 |
private void displayBoundingRect(float halfX, float halfY, float halfZ, DistortedOutputSurface surface, float[] mvp, float[] vertices)
|
|
| 187 | 187 |
{
|
| 188 | 188 |
int len = vertices.length/3; |
| 189 | 189 |
int minx = Integer.MAX_VALUE; |
| ... | ... | |
| 194 | 194 |
|
| 195 | 195 |
float x,y,z, X,Y,W, ndcX,ndcY; |
| 196 | 196 |
|
| 197 |
DistortedProjection projection = surface.getProjection(); |
|
| 198 |
|
|
| 197 | 199 |
for(int i=0; i<len; i++) |
| 198 | 200 |
{
|
| 199 | 201 |
x = 2*halfX*vertices[3*i ]; |
| ... | ... | |
| 207 | 209 |
ndcX = X/W; |
| 208 | 210 |
ndcY = Y/W; |
| 209 | 211 |
|
| 210 |
wx = (int)(df.mWidth *(ndcX+1)/2);
|
|
| 211 |
wy = (int)(df.mHeight*(ndcY+1)/2);
|
|
| 212 |
wx = (int)(projection.mWidth *(ndcX+1)/2);
|
|
| 213 |
wy = (int)(projection.mHeight*(ndcY+1)/2);
|
|
| 212 | 214 |
|
| 213 | 215 |
if( wx<minx ) minx = wx; |
| 214 | 216 |
if( wx>maxx ) maxx = wx; |
| ... | ... | |
| 217 | 219 |
} |
| 218 | 220 |
|
| 219 | 221 |
mDebugProgram.useProgram(); |
| 220 |
df.setAsOutput();
|
|
| 222 |
surface.setAsOutput();
|
|
| 221 | 223 |
|
| 222 | 224 |
Matrix.setIdentityM( mTmpMatrix, 0); |
| 223 |
Matrix.translateM ( mTmpMatrix, 0, minx-df.mWidth/2, maxy-df.mHeight/2, -df.mDistance);
|
|
| 225 |
Matrix.translateM ( mTmpMatrix, 0, minx-projection.mWidth/2, maxy-projection.mHeight/2, -projection.mDistance);
|
|
| 224 | 226 |
Matrix.scaleM ( mTmpMatrix, 0, (float)(maxx-minx)/(2*halfX), (float)(maxy-miny)/(2*halfY), 1.0f); |
| 225 | 227 |
Matrix.translateM ( mTmpMatrix, 0, halfX,-halfY, 0); |
| 226 |
Matrix.multiplyMM ( mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 228 |
Matrix.multiplyMM ( mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 227 | 229 |
|
| 228 | 230 |
GLES30.glUniform2f( mObjDH , 2*halfX, 2*halfY); |
| 229 | 231 |
GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0); |
| ... | ... | |
| 234 | 236 |
|
| 235 | 237 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 236 | 238 |
|
| 237 |
void drawPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df, long currTime)
|
|
| 239 |
void drawPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedOutputSurface surface, long currTime)
|
|
| 238 | 240 |
{
|
| 239 | 241 |
mM.compute(currTime); |
| 240 | 242 |
mV.compute(currTime); |
| ... | ... | |
| 242 | 244 |
mP.compute(currTime); |
| 243 | 245 |
|
| 244 | 246 |
float halfZ = halfInputW*mesh.zFactor; |
| 245 |
GLES30.glViewport(0, 0, df.mWidth, df.mHeight); |
|
| 247 |
DistortedProjection projection = surface.getProjection(); |
|
| 248 |
GLES30.glViewport(0, 0, projection.mWidth, projection.mHeight); |
|
| 246 | 249 |
|
| 247 | 250 |
if( mP.mNumEffects==0 ) |
| 248 | 251 |
{
|
| 249 | 252 |
mProgram.useProgram(); |
| 250 |
df.setAsOutput();
|
|
| 251 |
mM.send(df,halfInputW,halfInputH,halfZ);
|
|
| 253 |
surface.setAsOutput();
|
|
| 254 |
mM.send(projection,halfInputW,halfInputH,halfZ);
|
|
| 252 | 255 |
mV.send(halfInputW,halfInputH,halfZ); |
| 253 | 256 |
mF.send(halfInputW,halfInputH); |
| 254 | 257 |
GLES30.glVertexAttribPointer(mProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions); |
| ... | ... | |
| 260 | 263 |
{
|
| 261 | 264 |
if( mV.mNumEffects==0 && mF.mNumEffects==0 && (mesh instanceof MeshFlat) && mM.canUseShortcut() ) |
| 262 | 265 |
{
|
| 263 |
mM.constructMatrices(df,halfInputW,halfInputH);
|
|
| 264 |
mP.render(2*halfInputW, 2*halfInputH, mM.getMVP(), df);
|
|
| 266 |
mM.constructMatrices(projection,halfInputW,halfInputH);
|
|
| 267 |
mP.render(2*halfInputW, 2*halfInputH, mM.getMVP(), surface);
|
|
| 265 | 268 |
} |
| 266 | 269 |
else |
| 267 | 270 |
{
|
| 268 | 271 |
mProgram.useProgram(); |
| 269 |
mBufferFBO.resizeFast(df.mWidth, df.mHeight);
|
|
| 272 |
mBufferFBO.resizeFast(projection.mWidth, projection.mHeight);
|
|
| 270 | 273 |
mBufferFBO.setAsOutput(); |
| 271 | 274 |
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| 272 | 275 |
GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT); |
| 273 |
mM.send(mBufferFBO,halfInputW,halfInputH,halfZ); |
|
| 276 |
mM.send(mBufferFBO.getProjection(),halfInputW,halfInputH,halfZ);
|
|
| 274 | 277 |
mV.send(halfInputW,halfInputH,halfZ); |
| 275 | 278 |
mF.send(halfInputW,halfInputH); |
| 276 | 279 |
GLES30.glVertexAttribPointer(mProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions); |
| ... | ... | |
| 279 | 282 |
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, mesh.dataLength); |
| 280 | 283 |
|
| 281 | 284 |
Matrix.setIdentityM(mTmpMatrix, 0); |
| 282 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -df.mDistance);
|
|
| 283 |
Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 285 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -projection.mDistance);
|
|
| 286 |
Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 284 | 287 |
|
| 285 | 288 |
mBufferFBO.setAsInput(); |
| 286 |
mP.render(df.mWidth, df.mHeight, mMVPMatrix, df);
|
|
| 289 |
mP.render(projection.mWidth, projection.mHeight, mMVPMatrix, surface);
|
|
| 287 | 290 |
} |
| 288 | 291 |
} |
| 289 | 292 |
|
| ... | ... | |
| 294 | 297 |
|
| 295 | 298 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 296 | 299 |
|
| 297 |
static void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedFramebuffer df)
|
|
| 300 |
static void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedProjection projection)
|
|
| 298 | 301 |
{
|
| 299 |
GLES30.glViewport(0, 0, df.mWidth, df.mHeight);
|
|
| 302 |
GLES30.glViewport(0, 0, projection.mWidth, projection.mHeight);
|
|
| 300 | 303 |
|
| 301 | 304 |
Matrix.setIdentityM(mTmpMatrix, 0); |
| 302 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -df.mDistance);
|
|
| 303 |
Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 305 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -projection.mDistance);
|
|
| 306 |
Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 304 | 307 |
|
| 305 |
EffectQueueMatrix.sendZero(df,halfInputW,halfInputH,halfInputW*mesh.zFactor);
|
|
| 308 |
EffectQueueMatrix.sendZero(projection,halfInputW,halfInputH,halfInputW*mesh.zFactor);
|
|
| 306 | 309 |
EffectQueueVertex.sendZero(); |
| 307 | 310 |
EffectQueueFragment.sendZero(); |
| 308 | 311 |
|
| src/main/java/org/distorted/library/DistortedFramebuffer.java | ||
|---|---|---|
| 20 | 20 |
package org.distorted.library; |
| 21 | 21 |
|
| 22 | 22 |
import android.opengl.GLES30; |
| 23 |
import android.opengl.Matrix; |
|
| 24 | 23 |
|
| 25 | 24 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 26 | 25 |
/** |
| 27 | 26 |
* Class which represents a OpenGL Framebuffer object. |
| 28 | 27 |
* <p> |
| 29 |
* User is able to create either Framebuffers from objects already constructed outside |
|
| 30 |
* of the library (the first constructor; primary use case: the screen) or an offscreen |
|
| 31 |
* FBOs. |
|
| 32 |
* <p> |
|
| 33 |
* Keep all objects created in a static LinkedList. The point: we need to be able to mark |
|
| 34 |
* Framebuffers for deletion, and delete all marked objects later at a convenient time (that's |
|
| 35 |
* because we can only delete from a thread that holds the OpenGL context so here we provide a |
|
| 36 |
* framework where one is able to mark for deletion at any time and actual deletion takes place |
|
| 37 |
* on the next render). |
|
| 28 |
* User is able to create offscreen FBOs and both a) render to them b) use their COLOR0 attachment as |
|
| 29 |
* an input texture. |
|
| 38 | 30 |
*/ |
| 39 |
public class DistortedFramebuffer extends DistortedRenderable |
|
| 31 |
public class DistortedFramebuffer extends DistortedRenderable implements DistortedInputSurface, DistortedOutputSurface
|
|
| 40 | 32 |
{
|
| 41 | 33 |
private int[] mDepthH = new int[1]; |
| 42 | 34 |
private int[] mFBOH = new int[1]; |
| 43 |
|
|
| 44 | 35 |
private boolean mDepthEnabled; |
| 45 |
|
|
| 46 |
// Projection stuff |
|
| 47 |
private float mX, mY, mFOV; |
|
| 48 |
int mWidth,mHeight,mDepth; |
|
| 49 |
float mDistance; |
|
| 50 |
float[] mProjectionMatrix; |
|
| 36 |
private DistortedProjection mProjection; |
|
| 51 | 37 |
|
| 52 | 38 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 53 | 39 |
// Must be called from a thread holding OpenGL Context |
| 54 | 40 |
// Watch out - this has the side-effect of binding a Texture and a Framebuffer! |
| 55 | 41 |
|
| 56 |
void create() |
|
| 42 |
public void create()
|
|
| 57 | 43 |
{
|
| 58 | 44 |
if( mColorH[0]==NOT_CREATED_YET ) |
| 59 | 45 |
{
|
| ... | ... | |
| 146 | 132 |
if( mDepthEnabled ) mDepthH[0] = NOT_CREATED_YET; |
| 147 | 133 |
} |
| 148 | 134 |
|
| 149 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 150 |
|
|
| 151 |
void setAsOutput() |
|
| 152 |
{
|
|
| 153 |
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]); |
|
| 154 |
|
|
| 155 |
if( mDepthH[0]!=NOT_CREATED_YET ) |
|
| 156 |
{
|
|
| 157 |
GLES30.glEnable(GLES30.GL_DEPTH_TEST); |
|
| 158 |
GLES30.glDepthMask(true); |
|
| 159 |
} |
|
| 160 |
else |
|
| 161 |
{
|
|
| 162 |
GLES30.glDisable(GLES30.GL_DEPTH_TEST); |
|
| 163 |
GLES30.glDepthMask(false); |
|
| 164 |
} |
|
| 165 |
} |
|
| 166 |
|
|
| 167 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 168 |
|
|
| 169 |
private void createProjection() |
|
| 170 |
{
|
|
| 171 |
if( mWidth>0 && mHeight>1 ) |
|
| 172 |
{
|
|
| 173 |
if( mFOV>0.0f ) // perspective projection |
|
| 174 |
{
|
|
| 175 |
float left = (-mX-mWidth /2.0f)/mHeight; |
|
| 176 |
float right = (-mX+mWidth /2.0f)/mHeight; |
|
| 177 |
float bottom = (-mY-mHeight/2.0f)/mHeight; |
|
| 178 |
float top = (-mY+mHeight/2.0f)/mHeight; |
|
| 179 |
float near = (top-bottom) / (2.0f*(float)Math.tan(mFOV*Math.PI/360)); |
|
| 180 |
mDistance = mHeight*near/(top-bottom); |
|
| 181 |
float far = 2*mDistance-near; |
|
| 182 |
mDepth = (int)((far-near)/2); |
|
| 183 |
|
|
| 184 |
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far); |
|
| 185 |
} |
|
| 186 |
else // parallel projection |
|
| 187 |
{
|
|
| 188 |
float left = -mX-mWidth /2.0f; |
|
| 189 |
float right = -mX+mWidth /2.0f; |
|
| 190 |
float bottom = -mY-mHeight/2.0f; |
|
| 191 |
float top = -mY+mHeight/2.0f; |
|
| 192 |
float near = (mWidth+mHeight)/2; |
|
| 193 |
mDistance = 2*near; |
|
| 194 |
float far = 3*near; |
|
| 195 |
mDepth = (int)near; |
|
| 196 |
|
|
| 197 |
Matrix.orthoM(mProjectionMatrix, 0, left, right, bottom, top, near, far); |
|
| 198 |
} |
|
| 199 |
} |
|
| 200 |
} |
|
| 201 |
|
|
| 202 | 135 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 203 | 136 |
// if new size fits into the size of the underlying Texture, just change the projection without |
| 204 | 137 |
// reallocating the Texture. Otherwise, we need to reallocate. |
| ... | ... | |
| 207 | 140 |
|
| 208 | 141 |
void resizeFast(int width, int height) |
| 209 | 142 |
{
|
| 210 |
if( mWidth!=width || mHeight!=height )
|
|
| 143 |
if( mProjection.resize(width,height) )
|
|
| 211 | 144 |
{
|
| 212 |
mWidth = width; |
|
| 213 |
mHeight= height; |
|
| 214 |
|
|
| 215 |
createProjection(); |
|
| 216 |
|
|
| 217 |
if( mWidth> mSizeX || mHeight> mSizeY) |
|
| 145 |
if( width> mSizeX || height> mSizeY) |
|
| 218 | 146 |
{
|
| 219 |
mSizeX = mWidth;
|
|
| 220 |
mSizeY = mHeight;
|
|
| 147 |
mSizeX = width;
|
|
| 148 |
mSizeY = height;
|
|
| 221 | 149 |
delete(); |
| 222 | 150 |
} |
| 223 | 151 |
} |
| ... | ... | |
| 240 | 168 |
{
|
| 241 | 169 |
super(width,height,NOT_CREATED_YET); |
| 242 | 170 |
|
| 243 |
mProjectionMatrix = new float[16]; |
|
| 244 |
|
|
| 245 |
mHeight = height; |
|
| 246 |
mWidth = width; |
|
| 247 |
mFOV = 60.0f; |
|
| 248 |
mX = 0.0f; |
|
| 249 |
mY = 0.0f; |
|
| 171 |
mProjection = new DistortedProjection(width,height); |
|
| 250 | 172 |
mDepthEnabled= depthEnabled; |
| 251 | 173 |
mFBOH[0] = NOT_CREATED_YET; |
| 252 | 174 |
mDepthH[0] = NOT_CREATED_YET; |
| 253 |
|
|
| 254 |
createProjection(); |
|
| 255 | 175 |
} |
| 256 | 176 |
|
| 257 | 177 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 267 | 187 |
{
|
| 268 | 188 |
super(width,height,NOT_CREATED_YET); |
| 269 | 189 |
|
| 270 |
mProjectionMatrix = new float[16]; |
|
| 271 |
|
|
| 272 |
mHeight = height; |
|
| 273 |
mWidth = width; |
|
| 274 |
mFOV = 60.0f; |
|
| 275 |
mX = 0.0f; |
|
| 276 |
mY = 0.0f; |
|
| 190 |
mProjection = new DistortedProjection(width,height); |
|
| 277 | 191 |
mDepthEnabled= false; |
| 278 | 192 |
mFBOH[0] = NOT_CREATED_YET; |
| 279 | 193 |
mDepthH[0] = NOT_CREATED_YET; |
| 280 |
|
|
| 281 |
createProjection(); |
|
| 282 | 194 |
} |
| 283 | 195 |
|
| 284 | 196 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 285 | 197 |
/** |
| 286 |
* Create a new Framebuffer from an already created OpenGL Framebuffer. |
|
| 287 |
* <p> |
|
| 288 |
* Has to be followed by a 'resize()' to set the size. |
|
| 289 |
* |
|
| 290 |
* @param fbo the ID of a OpenGL Framebuffer object. Typically 0 (the screen) |
|
| 198 |
* Bind the underlying rectangle of pixels as a OpenGL Texture. |
|
| 291 | 199 |
*/ |
| 292 |
public DistortedFramebuffer(int fbo)
|
|
| 200 |
public boolean setAsInput()
|
|
| 293 | 201 |
{
|
| 294 |
super(0,0,DONT_CREATE); |
|
| 202 |
if( mColorH[0]>0 ) |
|
| 203 |
{
|
|
| 204 |
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[0]); |
|
| 205 |
return true; |
|
| 206 |
} |
|
| 207 |
|
|
| 208 |
return false; |
|
| 209 |
} |
|
| 295 | 210 |
|
| 296 |
mProjectionMatrix = new float[16]; |
|
| 211 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 212 |
/** |
|
| 213 |
* Bind this Surface as a Framebuffer we can render to. |
|
| 214 |
*/ |
|
| 215 |
public void setAsOutput() |
|
| 216 |
{
|
|
| 217 |
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]); |
|
| 297 | 218 |
|
| 298 |
mFOV = 60.0f; |
|
| 299 |
mX = 0.0f; |
|
| 300 |
mY = 0.0f; |
|
| 301 |
mDepthEnabled= true; |
|
| 302 |
mFBOH[0] = fbo; |
|
| 303 |
mDepthH[0] = DONT_CREATE; |
|
| 219 |
if( mDepthH[0]!=NOT_CREATED_YET ) |
|
| 220 |
{
|
|
| 221 |
GLES30.glEnable(GLES30.GL_DEPTH_TEST); |
|
| 222 |
GLES30.glDepthMask(true); |
|
| 223 |
} |
|
| 224 |
else |
|
| 225 |
{
|
|
| 226 |
GLES30.glDisable(GLES30.GL_DEPTH_TEST); |
|
| 227 |
GLES30.glDepthMask(false); |
|
| 228 |
} |
|
| 304 | 229 |
} |
| 305 | 230 |
|
| 306 | 231 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 322 | 247 |
* <p> |
| 323 | 248 |
* Must be called from a thread holding OpenGL Context. |
| 324 | 249 |
* |
| 325 |
* @param ren input Renderable to use.
|
|
| 250 |
* @param surface InputSurface to skin our Mesh with.
|
|
| 326 | 251 |
* @param mesh Class descendant from MeshObject |
| 327 | 252 |
* @param effects The DistortedEffects to use when rendering |
| 328 | 253 |
* @param time Current time, in milliseconds. |
| 329 | 254 |
*/ |
| 330 |
public void renderTo(DistortedRenderable ren, MeshObject mesh, DistortedEffects effects, long time)
|
|
| 255 |
public void renderTo(DistortedInputSurface surface, MeshObject mesh, DistortedEffects effects, long time)
|
|
| 331 | 256 |
{
|
| 332 |
ren.create(); // Watch out - this needs to be before
|
|
| 333 |
create(); // the 'setAsInput' because this has side-effects! |
|
| 257 |
surface.create(); // Watch out - this needs to be before
|
|
| 258 |
create(); // the 'setAsInput' because this has side-effects!
|
|
| 334 | 259 |
|
| 335 |
if( ren.setAsInput() )
|
|
| 260 |
if( surface.setAsInput() )
|
|
| 336 | 261 |
{
|
| 337 | 262 |
DistortedRenderable.deleteAllMarked(); |
| 338 |
effects.drawPriv(ren.getWidth()/2.0f, ren.getHeight()/2.0f, mesh, this, time);
|
|
| 263 |
effects.drawPriv(surface.getWidth()/2.0f, surface.getHeight()/2.0f, mesh, this, time);
|
|
| 339 | 264 |
} |
| 340 | 265 |
} |
| 341 | 266 |
|
| ... | ... | |
| 365 | 290 |
*/ |
| 366 | 291 |
public void setProjection(float fov, float x, float y) |
| 367 | 292 |
{
|
| 368 |
mFOV = fov; |
|
| 369 |
mX = x; |
|
| 370 |
mY = y; |
|
| 371 |
|
|
| 372 |
createProjection(); |
|
| 293 |
mProjection.set(fov,x,y); |
|
| 294 |
mProjection.createProjection(); |
|
| 373 | 295 |
} |
| 374 | 296 |
|
| 375 | 297 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 376 | 298 |
/** |
| 377 | 299 |
* Resize the underlying Framebuffer. |
| 378 | 300 |
* |
| 379 |
* As the Framebuffer is not created until the first render, typical usage of this API is actually |
|
| 380 |
* to set the size of an not-yet-created Framebuffer of an object that has been created with the |
|
| 381 |
* second constructor. |
|
| 382 |
* <p> |
|
| 383 |
* Fully creating an object, rendering to it, then resizing mid-render is also possible. Actual |
|
| 384 |
* resize takes place on the next render. |
|
| 385 |
* |
|
| 386 | 301 |
* @param width The new width. |
| 387 | 302 |
* @param height The new height. |
| 388 | 303 |
*/ |
| 389 | 304 |
public void resize(int width, int height) |
| 390 | 305 |
{
|
| 391 |
if( mWidth!=width || mHeight!=height )
|
|
| 306 |
if( mProjection.resize(width,height) )
|
|
| 392 | 307 |
{
|
| 393 |
mWidth = width; |
|
| 394 |
mHeight= height; |
|
| 395 | 308 |
mSizeX = width; |
| 396 | 309 |
mSizeY = height; |
| 397 |
|
|
| 398 |
createProjection(); |
|
| 399 |
|
|
| 400 | 310 |
if( mColorH[0]>0 ) markForDeletion(); |
| 401 | 311 |
} |
| 402 | 312 |
} |
| ... | ... | |
| 427 | 337 |
{
|
| 428 | 338 |
return mDepthEnabled; |
| 429 | 339 |
} |
| 340 |
|
|
| 341 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 342 |
/** |
|
| 343 |
* Return Projection stored in this Framebuffer. |
|
| 344 |
* |
|
| 345 |
* @return DistortedProjection object. |
|
| 346 |
*/ |
|
| 347 |
public DistortedProjection getProjection() |
|
| 348 |
{
|
|
| 349 |
return mProjection; |
|
| 350 |
} |
|
| 430 | 351 |
} |
| src/main/java/org/distorted/library/DistortedInputSurface.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2016 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Distorted. // |
|
| 5 |
// // |
|
| 6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
| 7 |
// it under the terms of the GNU General Public License as published by // |
|
| 8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
| 9 |
// (at your option) any later version. // |
|
| 10 |
// // |
|
| 11 |
// Distorted is distributed in the hope that it will be useful, // |
|
| 12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
| 13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
| 14 |
// GNU General Public License for more details. // |
|
| 15 |
// // |
|
| 16 |
// You should have received a copy of the GNU General Public License // |
|
| 17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
| 18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 19 |
|
|
| 20 |
package org.distorted.library; |
|
| 21 |
|
|
| 22 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 23 |
|
|
| 24 |
/** |
|
| 25 |
* A Surface that we can set as Input, i.e. take its rectangle of pixels and skin our Mesh with it. |
|
| 26 |
*/ |
|
| 27 |
|
|
| 28 |
public interface DistortedInputSurface extends DistortedSurface |
|
| 29 |
{
|
|
| 30 |
/** |
|
| 31 |
* Take the underlying rectangle of pixels and bind this texture to OpenGL. |
|
| 32 |
*/ |
|
| 33 |
boolean setAsInput(); |
|
| 34 |
} |
|
| src/main/java/org/distorted/library/DistortedOutputSurface.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2016 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Distorted. // |
|
| 5 |
// // |
|
| 6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
| 7 |
// it under the terms of the GNU General Public License as published by // |
|
| 8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
| 9 |
// (at your option) any later version. // |
|
| 10 |
// // |
|
| 11 |
// Distorted is distributed in the hope that it will be useful, // |
|
| 12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
| 13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
| 14 |
// GNU General Public License for more details. // |
|
| 15 |
// // |
|
| 16 |
// You should have received a copy of the GNU General Public License // |
|
| 17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
| 18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 19 |
|
|
| 20 |
package org.distorted.library; |
|
| 21 |
|
|
| 22 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 23 |
|
|
| 24 |
/** |
|
| 25 |
* A Surface that we can set as Output, i.e. render to it. |
|
| 26 |
*/ |
|
| 27 |
|
|
| 28 |
public interface DistortedOutputSurface extends DistortedSurface |
|
| 29 |
{
|
|
| 30 |
/** |
|
| 31 |
* Bind this Surface as a Framebuffer we can render to. |
|
| 32 |
*/ |
|
| 33 |
void setAsOutput(); |
|
| 34 |
/** |
|
| 35 |
* Return the Projection. |
|
| 36 |
*/ |
|
| 37 |
DistortedProjection getProjection(); |
|
| 38 |
} |
|
| src/main/java/org/distorted/library/DistortedProjection.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2016 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Distorted. // |
|
| 5 |
// // |
|
| 6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
| 7 |
// it under the terms of the GNU General Public License as published by // |
|
| 8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
| 9 |
// (at your option) any later version. // |
|
| 10 |
// // |
|
| 11 |
// Distorted is distributed in the hope that it will be useful, // |
|
| 12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
| 13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
| 14 |
// GNU General Public License for more details. // |
|
| 15 |
// // |
|
| 16 |
// You should have received a copy of the GNU General Public License // |
|
| 17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
| 18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 19 |
|
|
| 20 |
package org.distorted.library; |
|
| 21 |
|
|
| 22 |
import android.opengl.Matrix; |
|
| 23 |
|
|
| 24 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 25 |
|
|
| 26 |
class DistortedProjection |
|
| 27 |
{
|
|
| 28 |
private float mX, mY, mFOV; |
|
| 29 |
int mWidth,mHeight,mDepth; |
|
| 30 |
float mDistance; |
|
| 31 |
float[] mProjectionMatrix; |
|
| 32 |
|
|
| 33 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 34 |
|
|
| 35 |
DistortedProjection() |
|
| 36 |
{
|
|
| 37 |
mProjectionMatrix = new float[16]; |
|
| 38 |
|
|
| 39 |
mWidth = 0; |
|
| 40 |
mHeight= 0; |
|
| 41 |
|
|
| 42 |
mFOV = 60.0f; |
|
| 43 |
mX = 0.0f; |
|
| 44 |
mY = 0.0f; |
|
| 45 |
} |
|
| 46 |
|
|
| 47 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 48 |
|
|
| 49 |
DistortedProjection(int width, int height) |
|
| 50 |
{
|
|
| 51 |
mProjectionMatrix = new float[16]; |
|
| 52 |
|
|
| 53 |
mWidth = width; |
|
| 54 |
mHeight= height; |
|
| 55 |
|
|
| 56 |
mFOV = 60.0f; |
|
| 57 |
mX = 0.0f; |
|
| 58 |
mY = 0.0f; |
|
| 59 |
|
|
| 60 |
createProjection(); |
|
| 61 |
} |
|
| 62 |
|
|
| 63 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 64 |
|
|
| 65 |
boolean resize(int width, int height) |
|
| 66 |
{
|
|
| 67 |
if( mWidth!=width || mHeight!=height ) |
|
| 68 |
{
|
|
| 69 |
mWidth = width; |
|
| 70 |
mHeight= height; |
|
| 71 |
createProjection(); |
|
| 72 |
return true; |
|
| 73 |
} |
|
| 74 |
|
|
| 75 |
return false; |
|
| 76 |
} |
|
| 77 |
|
|
| 78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 79 |
|
|
| 80 |
void set(float fov, float x, float y) |
|
| 81 |
{
|
|
| 82 |
mFOV = fov; |
|
| 83 |
mX = x; |
|
| 84 |
mY = y; |
|
| 85 |
} |
|
| 86 |
|
|
| 87 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 88 |
|
|
| 89 |
void createProjection() |
|
| 90 |
{
|
|
| 91 |
if( mWidth>0 && mHeight>1 ) |
|
| 92 |
{
|
|
| 93 |
if( mFOV>0.0f ) // perspective projection |
|
| 94 |
{
|
|
| 95 |
float left = (-mX-mWidth /2.0f)/mHeight; |
|
| 96 |
float right = (-mX+mWidth /2.0f)/mHeight; |
|
| 97 |
float bottom = (-mY-mHeight/2.0f)/mHeight; |
|
| 98 |
float top = (-mY+mHeight/2.0f)/mHeight; |
|
| 99 |
float near = (top-bottom) / (2.0f*(float)Math.tan(mFOV*Math.PI/360)); |
|
| 100 |
mDistance = mHeight*near/(top-bottom); |
|
| 101 |
float far = 2*mDistance-near; |
|
| 102 |
mDepth = (int)((far-near)/2); |
|
| 103 |
|
|
| 104 |
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far); |
|
| 105 |
} |
|
| 106 |
else // parallel projection |
|
| 107 |
{
|
|
| 108 |
float left = -mX-mWidth /2.0f; |
|
| 109 |
float right = -mX+mWidth /2.0f; |
|
| 110 |
float bottom = -mY-mHeight/2.0f; |
|
| 111 |
float top = -mY+mHeight/2.0f; |
|
| 112 |
float near = (mWidth+mHeight)/2; |
|
| 113 |
mDistance = 2*near; |
|
| 114 |
float far = 3*near; |
|
| 115 |
mDepth = (int)near; |
|
| 116 |
|
|
| 117 |
Matrix.orthoM(mProjectionMatrix, 0, left, right, bottom, top, near, far); |
|
| 118 |
} |
|
| 119 |
} |
|
| 120 |
} |
|
| 121 |
|
|
| 122 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 123 |
|
|
| 124 |
} |
|
| src/main/java/org/distorted/library/DistortedRenderable.java | ||
|---|---|---|
| 19 | 19 |
|
| 20 | 20 |
package org.distorted.library; |
| 21 | 21 |
|
| 22 |
import android.opengl.GLES30; |
|
| 23 |
|
|
| 24 | 22 |
import java.util.Iterator; |
| 25 | 23 |
import java.util.LinkedList; |
| 26 | 24 |
|
| 27 | 25 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 28 | 26 |
/** |
| 29 |
* Abstract class which represents a Renderable Object, i.e. something that we can take an skin our Mesh with. |
|
| 30 |
* <p> |
|
| 31 |
* Currently a DistortedTexture or a DistortedFramebuffer are Renderables. |
|
| 32 |
*/ |
|
| 33 |
public abstract class DistortedRenderable |
|
| 27 |
* Keep all objects created in a static LinkedList. The point: we need to be able to mark |
|
| 28 |
* Objects for deletion, and delete all marked Objects later at a convenient time (that's |
|
| 29 |
* because we can only delete from a thread that holds the OpenGL context so here we provide a |
|
| 30 |
* framework where one is able to mark for deletion at any time and actual deletion takes place |
|
| 31 |
* on the next render). |
|
| 32 |
*/ |
|
| 33 |
abstract class DistortedRenderable implements DistortedSurface |
|
| 34 | 34 |
{
|
| 35 | 35 |
static final int FAILED_TO_CREATE = -1; |
| 36 | 36 |
static final int NOT_CREATED_YET = -2; |
| ... | ... | |
| 45 | 45 |
|
| 46 | 46 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 47 | 47 |
|
| 48 |
abstract void create(); |
|
| 48 |
public abstract void create();
|
|
| 49 | 49 |
abstract void delete(); |
| 50 | 50 |
abstract void destroy(); |
| 51 | 51 |
|
| ... | ... | |
| 75 | 75 |
} |
| 76 | 76 |
} |
| 77 | 77 |
|
| 78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 79 |
|
|
| 80 |
long getID() |
|
| 81 |
{
|
|
| 82 |
return mColorH[0]; |
|
| 83 |
} |
|
| 84 |
|
|
| 85 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 86 |
|
|
| 87 |
boolean setAsInput() |
|
| 88 |
{
|
|
| 89 |
if( mColorH[0]>0 ) |
|
| 90 |
{
|
|
| 91 |
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[0]); |
|
| 92 |
return true; |
|
| 93 |
} |
|
| 94 |
|
|
| 95 |
return false; |
|
| 96 |
} |
|
| 97 |
|
|
| 98 | 78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 99 | 79 |
|
| 100 | 80 |
static synchronized void onDestroy() |
| ... | ... | |
| 131 | 111 |
mMarked = true; |
| 132 | 112 |
} |
| 133 | 113 |
|
| 114 |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 115 |
/** |
|
| 116 |
* Return unique ID of the Renderable. |
|
| 117 |
*/ |
|
| 118 |
public long getID() |
|
| 119 |
{
|
|
| 120 |
return mColorH[0]; |
|
| 121 |
} |
|
| 122 |
|
|
| 134 | 123 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 135 | 124 |
|
| 136 | 125 |
/** |
| src/main/java/org/distorted/library/DistortedScreen.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2016 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Distorted. // |
|
| 5 |
// // |
|
| 6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
| 7 |
// it under the terms of the GNU General Public License as published by // |
|
| 8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
| 9 |
// (at your option) any later version. // |
|
| 10 |
// // |
|
| 11 |
// Distorted is distributed in the hope that it will be useful, // |
|
| 12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
| 13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
| 14 |
// GNU General Public License for more details. // |
|
| 15 |
// // |
|
| 16 |
// You should have received a copy of the GNU General Public License // |
|
| 17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
| 18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 19 |
|
|
| 20 |
package org.distorted.library; |
|
| 21 |
|
|
| 22 |
import android.opengl.GLES30; |
|
| 23 |
|
|
| 24 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 25 |
/** |
|
| 26 |
* Class which represents the Screen. |
|
| 27 |
* <p> |
|
| 28 |
* User is able to render to it just like to a DistortedFramebuffer. |
|
| 29 |
*/ |
|
| 30 |
public class DistortedScreen extends DistortedRenderable implements DistortedOutputSurface |
|
| 31 |
{
|
|
| 32 |
private int[] mFBOH = new int[1]; |
|
| 33 |
private DistortedProjection mProjection; |
|
| 34 |
|
|
| 35 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 36 |
|
|
| 37 |
public void create() {}
|
|
| 38 |
void delete() {}
|
|
| 39 |
void destroy() {}
|
|
| 40 |
|
|
| 41 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 42 |
// PUBLIC API |
|
| 43 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 44 |
/** |
|
| 45 |
* Create a new Screen. |
|
| 46 |
* <p> |
|
| 47 |
* Has to be followed by a 'resize()' to set the size. |
|
| 48 |
*/ |
|
| 49 |
public DistortedScreen() |
|
| 50 |
{
|
|
| 51 |
super(0,0,DONT_CREATE); |
|
| 52 |
|
|
| 53 |
mProjection = new DistortedProjection(); |
|
| 54 |
mFBOH[0] = 0; |
|
| 55 |
} |
|
| 56 |
|
|
| 57 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 58 |
/** |
|
| 59 |
* Bind this Surface as a Framebuffer we can render to. |
|
| 60 |
*/ |
|
| 61 |
public void setAsOutput() |
|
| 62 |
{
|
|
| 63 |
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]); |
|
| 64 |
GLES30.glEnable(GLES30.GL_DEPTH_TEST); |
|
| 65 |
GLES30.glDepthMask(true); |
|
| 66 |
} |
|
| 67 |
|
|
| 68 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 69 |
|
|
| 70 |
/** |
|
| 71 |
* Draw the (texture,mesh,effects) object to the Framebuffer. |
|
| 72 |
* <p> |
|
| 73 |
* Must be called from a thread holding OpenGL Context. |
|
| 74 |
* |
|
| 75 |
* @param surface InputSurface to skin our Mesh with. |
|
| 76 |
* @param mesh Class descendant from MeshObject |
|
| 77 |
* @param effects The DistortedEffects to use when rendering |
|
| 78 |
* @param time Current time, in milliseconds. |
|
| 79 |
*/ |
|
| 80 |
public void renderTo(DistortedInputSurface surface, MeshObject mesh, DistortedEffects effects, long time) |
|
| 81 |
{
|
|
| 82 |
surface.create(); // Watch out - this needs to be before |
|
| 83 |
create(); // the 'setAsInput' because this has side-effects! |
|
| 84 |
|
|
| 85 |
if( surface.setAsInput() ) |
|
| 86 |
{
|
|
| 87 |
DistortedRenderable.deleteAllMarked(); |
|
| 88 |
effects.drawPriv(surface.getWidth()/2.0f, surface.getHeight()/2.0f, mesh, this, time); |
|
| 89 |
} |
|
| 90 |
} |
|
| 91 |
|
|
| 92 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 93 |
/** |
|
| 94 |
* Draws the Tree, and all its children, to the Framebuffer. |
|
| 95 |
* <p> |
|
| 96 |
* Must be called from a thread holding OpenGL Context. |
|
| 97 |
* |
|
| 98 |
* @param dt DistortedTree to render. |
|
| 99 |
* @param time Current time, in milliseconds. This will be passed to all the Effects stored in the Tree. |
|
| 100 |
*/ |
|
| 101 |
public void renderTo(DistortedTree dt, long time) |
|
| 102 |
{
|
|
| 103 |
DistortedRenderable.deleteAllMarked(); |
|
| 104 |
create(); |
|
| 105 |
dt.drawRecursive(time,this); |
|
| 106 |
} |
|
| 107 |
|
|
| 108 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 109 |
/** |
|
| 110 |
* Create new Projection matrix. |
|
| 111 |
* |
|
| 112 |
* @param fov Vertical 'field of view' of the Projection frustrum (in degrees). |
|
| 113 |
* @param x X-coordinate of the point at which our camera looks at. 0 is the center. |
|
| 114 |
* @param y Y-coordinate of the point at which our camera looks at. 0 is the center. |
|
| 115 |
*/ |
|
| 116 |
public void setProjection(float fov, float x, float y) |
|
| 117 |
{
|
|
| 118 |
mProjection.set(fov,x,y); |
|
| 119 |
mProjection.createProjection(); |
|
| 120 |
} |
|
| 121 |
|
|
| 122 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 123 |
/** |
|
| 124 |
* Resize the underlying Projection. |
|
| 125 |
* |
|
| 126 |
* @param width The new width. |
|
| 127 |
* @param height The new height. |
|
| 128 |
*/ |
|
| 129 |
public void resize(int width, int height) |
|
| 130 |
{
|
|
| 131 |
if( mProjection.resize(width,height) ) |
|
| 132 |
{
|
|
| 133 |
mSizeX = width; |
|
| 134 |
mSizeY = height; |
|
| 135 |
} |
|
| 136 |
} |
|
| 137 |
|
|
| 138 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 139 |
/** |
|
| 140 |
* Return Projection stored in this Framebuffer. |
|
| 141 |
* |
|
| 142 |
* @return DistortedProjection object. |
|
| 143 |
*/ |
|
| 144 |
public DistortedProjection getProjection() |
|
| 145 |
{
|
|
| 146 |
return mProjection; |
|
| 147 |
} |
|
| 148 |
} |
|
| src/main/java/org/distorted/library/DistortedSurface.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2016 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Distorted. // |
|
| 5 |
// // |
|
| 6 |
// Distorted is free software: you can redistribute it and/or modify // |
|
| 7 |
// it under the terms of the GNU General Public License as published by // |
|
| 8 |
// the Free Software Foundation, either version 2 of the License, or // |
|
| 9 |
// (at your option) any later version. // |
|
| 10 |
// // |
|
| 11 |
// Distorted is distributed in the hope that it will be useful, // |
|
| 12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
| 13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // |
|
| 14 |
// GNU General Public License for more details. // |
|
| 15 |
// // |
|
| 16 |
// You should have received a copy of the GNU General Public License // |
|
| 17 |
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. // |
|
| 18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 19 |
|
|
| 20 |
package org.distorted.library; |
|
| 21 |
|
|
| 22 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 23 |
|
|
| 24 |
/** |
|
| 25 |
* Abstract Surface. |
|
| 26 |
*/ |
|
| 27 |
|
|
| 28 |
interface DistortedSurface |
|
| 29 |
{
|
|
| 30 |
/** |
|
| 31 |
* Create the underlying OpenGL part of the Surface. |
|
| 32 |
*/ |
|
| 33 |
void create(); |
|
| 34 |
/** |
|
| 35 |
* Return a unique ID of this Surface. |
|
| 36 |
*/ |
|
| 37 |
long getID(); |
|
| 38 |
/** |
|
| 39 |
* Return the width of this Surface. |
|
| 40 |
*/ |
|
| 41 |
int getWidth(); |
|
| 42 |
/** |
|
| 43 |
* Return the height of this Surface. |
|
| 44 |
*/ |
|
| 45 |
int getHeight(); |
|
| 46 |
} |
|
| src/main/java/org/distorted/library/DistortedTexture.java | ||
|---|---|---|
| 29 | 29 |
* Class which represents a OpenGL Texture object. |
| 30 | 30 |
* <p> |
| 31 | 31 |
* Create a Texture of arbitrary size and feed some pixels to it via the setTexture() method. |
| 32 |
* <p> |
|
| 33 |
* Keep all objects created in a static LinkedList. The point: we need to be able to mark |
|
| 34 |
* Textures for deletion, and delete all marked objects later at a convenient time (that's |
|
| 35 |
* because we can only delete from a thread that holds the OpenGL context so here we provide a |
|
| 36 |
* framework where one is able to mark for deletion at any time and actual deletion takes place |
|
| 37 |
* on the next render). |
|
| 38 | 32 |
*/ |
| 39 |
public class DistortedTexture extends DistortedRenderable |
|
| 33 |
public class DistortedTexture extends DistortedRenderable implements DistortedInputSurface
|
|
| 40 | 34 |
{
|
| 41 | 35 |
private Bitmap mBmp= null; |
| 42 | 36 |
|
| ... | ... | |
| 61 | 55 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 62 | 56 |
// must be called from a thread holding OpenGL Context |
| 63 | 57 |
|
| 64 |
void create() |
|
| 58 |
public void create()
|
|
| 65 | 59 |
{
|
| 66 | 60 |
if( mBmp!=null && mColorH !=null ) |
| 67 | 61 |
{
|
| ... | ... | |
| 104 | 98 |
{
|
| 105 | 99 |
if( mColorH[0]!=DONT_CREATE ) mColorH[0] = NOT_CREATED_YET; |
| 106 | 100 |
} |
| 101 |
|
|
| 107 | 102 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 108 | 103 |
|
| 109 | 104 |
static void getUniforms(int mProgramH) |
| ... | ... | |
| 126 | 121 |
mBmp= null; |
| 127 | 122 |
} |
| 128 | 123 |
|
| 124 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 125 |
/** |
|
| 126 |
* Bind the underlying rectangle of pixels as a OpenGL Texture. |
|
| 127 |
*/ |
|
| 128 |
public boolean setAsInput() |
|
| 129 |
{
|
|
| 130 |
if( mColorH[0]>0 ) |
|
| 131 |
{
|
|
| 132 |
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[0]); |
|
| 133 |
return true; |
|
| 134 |
} |
|
| 135 |
|
|
| 136 |
return false; |
|
| 137 |
} |
|
| 138 |
|
|
| 129 | 139 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 130 | 140 |
/** |
| 131 | 141 |
* Sets the underlying android.graphics.Bitmap object. |
| src/main/java/org/distorted/library/DistortedTree.java | ||
|---|---|---|
| 38 | 38 |
|
| 39 | 39 |
private MeshObject mMesh; |
| 40 | 40 |
private DistortedEffects mEffects; |
| 41 |
private DistortedRenderable mRenderable;
|
|
| 41 |
private DistortedInputSurface mSurface;
|
|
| 42 | 42 |
private NodeData mData; |
| 43 | 43 |
|
| 44 | 44 |
private DistortedTree mParent; |
| ... | ... | |
| 94 | 94 |
{
|
| 95 | 95 |
ArrayList<Long> ret = new ArrayList<>(); |
| 96 | 96 |
|
| 97 |
ret.add( mRenderable.getID() );
|
|
| 97 |
ret.add( mSurface.getID() );
|
|
| 98 | 98 |
DistortedTree node; |
| 99 | 99 |
|
| 100 | 100 |
for(int i=0; i<mNumChildren[0]; i++) |
| ... | ... | |
| 125 | 125 |
if( newList.size()>1 ) |
| 126 | 126 |
{
|
| 127 | 127 |
if( mData.mFBO ==null ) |
| 128 |
mData.mFBO = new DistortedFramebuffer(mRenderable.getWidth(), mRenderable.getHeight());
|
|
| 128 |
mData.mFBO = new DistortedFramebuffer(mSurface.getWidth(), mSurface.getHeight());
|
|
| 129 | 129 |
} |
| 130 | 130 |
else |
| 131 | 131 |
{
|
| ... | ... | |
| 198 | 198 |
*/ |
| 199 | 199 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 200 | 200 |
|
| 201 |
void drawRecursive(long currTime, DistortedFramebuffer df)
|
|
| 201 |
void drawRecursive(long currTime, DistortedOutputSurface surface)
|
|
| 202 | 202 |
{
|
| 203 |
mRenderable.create();
|
|
| 204 |
float halfX = mRenderable.getWidth()/2.0f;
|
|
| 205 |
float halfY = mRenderable.getHeight()/2.0f;
|
|
| 203 |
mSurface.create();
|
|
| 204 |
float halfX = mSurface.getWidth()/2.0f;
|
|
| 205 |
float halfY = mSurface.getHeight()/2.0f;
|
|
| 206 | 206 |
|
| 207 | 207 |
if( mNumChildren[0]<=0 ) |
| 208 | 208 |
{
|
| 209 |
mRenderable.setAsInput();
|
|
| 209 |
mSurface.setAsInput();
|
|
| 210 | 210 |
} |
| 211 | 211 |
else |
| 212 | 212 |
{
|
| ... | ... | |
| 219 | 219 |
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| 220 | 220 |
GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT); |
| 221 | 221 |
|
| 222 |
if( mRenderable.setAsInput() )
|
|
| 223 |
DistortedEffects.drawNoEffectsPriv(halfX, halfY, mMesh, mData.mFBO); |
|
| 222 |
if( mSurface.setAsInput() )
|
|
| 223 |
DistortedEffects.drawNoEffectsPriv(halfX, halfY, mMesh, mData.mFBO.getProjection() );
|
|
| 224 | 224 |
|
| 225 | 225 |
synchronized(this) |
| 226 | 226 |
{
|
| ... | ... | |
| 236 | 236 |
mData.mFBO.setAsInput(); |
| 237 | 237 |
} |
| 238 | 238 |
|
| 239 |
mEffects.drawPriv(halfX, halfY, mMesh, df, currTime);
|
|
| 239 |
mEffects.drawPriv(halfX, halfY, mMesh, surface, currTime);
|
|
| 240 | 240 |
} |
| 241 | 241 |
|
| 242 | 242 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 245 | 245 |
/** |
| 246 | 246 |
* Constructs new Node of the Tree. |
| 247 | 247 |
* |
| 248 |
* @param renderable DistortedRenderable to put into the new Node.
|
|
| 248 |
* @param surface InputSurface to put into the new Node.
|
|
| 249 | 249 |
* @param effects DistortedEffects to put into the new Node. |
| 250 | 250 |
* @param mesh MeshObject to put into the new Node. |
| 251 | 251 |
*/ |
| 252 |
public DistortedTree(DistortedRenderable renderable, DistortedEffects effects, MeshObject mesh)
|
|
| 252 |
public DistortedTree(DistortedInputSurface surface, DistortedEffects effects, MeshObject mesh)
|
|
| 253 | 253 |
{
|
| 254 |
mRenderable = renderable;
|
|
| 254 |
mSurface = surface;
|
|
| 255 | 255 |
mEffects = effects; |
| 256 | 256 |
mMesh = mesh; |
| 257 | 257 |
mParent = null; |
| ... | ... | |
| 260 | 260 |
mNumChildren[0]= 0; |
| 261 | 261 |
|
| 262 | 262 |
ArrayList<Long> list = new ArrayList<>(); |
| 263 |
list.add(mRenderable.getID());
|
|
| 263 |
list.add(mSurface.getID());
|
|
| 264 | 264 |
|
| 265 | 265 |
mData = mMapNodeID.get(list); |
| 266 | 266 |
|
| ... | ... | |
| 293 | 293 |
|
| 294 | 294 |
if( (flags & Distorted.CLONE_RENDERABLE) != 0 ) |
| 295 | 295 |
{
|
| 296 |
mRenderable = node.mRenderable;
|
|
| 296 |
mSurface = node.mSurface;
|
|
| 297 | 297 |
} |
| 298 | 298 |
else |
| 299 | 299 |
{
|
| 300 |
int w = node.mRenderable.getWidth();
|
|
| 301 |
int h = node.mRenderable.getHeight();
|
|
| 300 |
int w = node.mSurface.getWidth();
|
|
| 301 |
int h = node.mSurface.getHeight();
|
|
| 302 | 302 |
|
| 303 |
if( node.mRenderable instanceof DistortedTexture )
|
|
| 303 |
if( node.mSurface instanceof DistortedTexture )
|
|
| 304 | 304 |
{
|
| 305 |
mRenderable = new DistortedTexture(w,h);
|
|
| 305 |
mSurface = new DistortedTexture(w,h);
|
|
| 306 | 306 |
} |
| 307 |
else if( node.mRenderable instanceof DistortedFramebuffer )
|
|
| 307 |
else if( node.mSurface instanceof DistortedFramebuffer )
|
|
| 308 | 308 |
{
|
| 309 |
boolean hasDepth = ((DistortedFramebuffer) node.mRenderable).hasDepth();
|
|
| 310 |
mRenderable = new DistortedFramebuffer(w,h,hasDepth);
|
|
| 309 |
boolean hasDepth = ((DistortedFramebuffer) node.mSurface).hasDepth();
|
|
| 310 |
mSurface = new DistortedFramebuffer(w,h,hasDepth);
|
|
| 311 | 311 |
} |
| 312 | 312 |
} |
| 313 | 313 |
if( (flags & Distorted.CLONE_CHILDREN) != 0 ) |
| ... | ... | |
| 360 | 360 |
/** |
| 361 | 361 |
* Adds a new child to the last position in the list of our Node's children. |
| 362 | 362 |
* |
| 363 |
* @param renderable DistortedRenderable to initialize our child Node with.
|
|
| 363 |
* @param surface InputSurface to initialize our child Node with.
|
|
| 364 | 364 |
* @param effects DistortedEffects to initialize our child Node with. |
| 365 | 365 |
* @param mesh MeshObject to initialize our child Node with. |
| 366 | 366 |
* @return the newly constructed child Node, or null if we couldn't allocate resources. |
| 367 | 367 |
*/ |
| 368 |
public synchronized DistortedTree attach(DistortedRenderable renderable, DistortedEffects effects, MeshObject mesh)
|
|
| 368 |
public synchronized DistortedTree attach(DistortedInputSurface surface, DistortedEffects effects, MeshObject mesh)
|
|
| 369 | 369 |
{
|
| 370 | 370 |
ArrayList<Long> prev = generateIDList(); |
| 371 | 371 |
|
| 372 | 372 |
if( mChildren==null ) mChildren = new ArrayList<>(2); |
| 373 |
DistortedTree node = new DistortedTree(renderable,effects,mesh);
|
|
| 373 |
DistortedTree node = new DistortedTree(surface,effects,mesh);
|
|
| 374 | 374 |
node.mParent = this; |
| 375 | 375 |
mChildren.add(node); |
| 376 | 376 |
mNumChildren[0]++; |
| ... | ... | |
| 474 | 474 |
|
| 475 | 475 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 476 | 476 |
/** |
| 477 |
* Returns the DistortedRenderable object that's in the Node.
|
|
| 477 |
* Returns the DistortedInputSurface object that's in the Node.
|
|
| 478 | 478 |
* |
| 479 |
* @return The DistortedRenderable contained in the Node.
|
|
| 479 |
* @return The DistortedInputSurface contained in the Node.
|
|
| 480 | 480 |
*/ |
| 481 |
public DistortedRenderable getRenderable()
|
|
| 481 |
public DistortedInputSurface getSurface()
|
|
| 482 | 482 |
{
|
| 483 |
return mRenderable;
|
|
| 483 |
return mSurface;
|
|
| 484 | 484 |
} |
| 485 | 485 |
|
| 486 | 486 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| src/main/java/org/distorted/library/EffectQueueMatrix.java | ||
|---|---|---|
| 107 | 107 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 108 | 108 |
// here construct the ModelView and the ModelViewProjection Matrices |
| 109 | 109 |
|
| 110 |
void constructMatrices(DistortedFramebuffer df, float halfX, float halfY)
|
|
| 110 |
void constructMatrices(DistortedProjection projection, float halfX, float halfY)
|
|
| 111 | 111 |
{
|
| 112 | 112 |
Matrix.setIdentityM(mViewMatrix, 0); |
| 113 |
Matrix.translateM(mViewMatrix, 0, -df.mWidth/2, df.mHeight/2, -df.mDistance);
|
|
| 113 |
Matrix.translateM(mViewMatrix, 0, -projection.mWidth/2, projection.mHeight/2, -projection.mDistance);
|
|
| 114 | 114 |
|
| 115 | 115 |
float x,y,z, sx,sy,sz; |
| 116 | 116 |
|
| ... | ... | |
| 184 | 184 |
} |
| 185 | 185 |
|
| 186 | 186 |
Matrix.translateM(mViewMatrix, 0, halfX,-halfY, 0); |
| 187 |
Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mViewMatrix, 0);
|
|
| 187 |
Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mViewMatrix, 0);
|
|
| 188 | 188 |
} |
| 189 | 189 |
|
| 190 | 190 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 284 | 284 |
|
| 285 | 285 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 286 | 286 |
|
| 287 |
synchronized void send(DistortedFramebuffer df, float halfX, float halfY, float halfZ)
|
|
| 287 |
synchronized void send(DistortedProjection projection, float halfX, float halfY, float halfZ)
|
|
| 288 | 288 |
{
|
| 289 |
constructMatrices(df,halfX,halfY);
|
|
| 289 |
constructMatrices(projection,halfX,halfY);
|
|
| 290 | 290 |
|
| 291 | 291 |
GLES30.glUniform3f( mObjDH , halfX, halfY, halfZ); |
| 292 |
GLES30.glUniform1f( mDepthH, df.mDepth);
|
|
| 292 |
GLES30.glUniform1f( mDepthH, projection.mDepth);
|
|
| 293 | 293 |
GLES30.glUniformMatrix4fv(mMVMatrixH , 1, false, mViewMatrix, 0); |
| 294 | 294 |
GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0); |
| 295 | 295 |
} |
| ... | ... | |
| 297 | 297 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 298 | 298 |
// here construct the ModelView Matrix, but without any effects |
| 299 | 299 |
|
| 300 |
synchronized static void sendZero(DistortedFramebuffer df, float halfX, float halfY, float halfZ)
|
|
| 300 |
synchronized static void sendZero(DistortedProjection projection, float halfX, float halfY, float halfZ)
|
|
| 301 | 301 |
{
|
| 302 | 302 |
Matrix.setIdentityM(mTmpMatrix, 0); |
| 303 |
Matrix.translateM(mTmpMatrix, 0, halfX-df.mWidth/2, df.mHeight/2-halfY, -df.mDistance);
|
|
| 304 |
Matrix.multiplyMM(mMVPMatrix, 0, df.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 303 |
Matrix.translateM(mTmpMatrix, 0, halfX-projection.mWidth/2, projection.mHeight/2-halfY, -projection.mDistance);
|
|
| 304 |
Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 305 | 305 |
|
| 306 | 306 |
GLES30.glUniform3f( mObjDH , halfX, halfY, halfZ); |
| 307 |
GLES30.glUniform1f( mDepthH, df.mDepth);
|
|
| 307 |
GLES30.glUniform1f( mDepthH, projection.mDepth);
|
|
| 308 | 308 |
GLES30.glUniformMatrix4fv(mMVMatrixH , 1, false, mTmpMatrix, 0); |
| 309 | 309 |
GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix, 0); |
| 310 | 310 |
} |
| src/main/java/org/distorted/library/EffectQueuePostprocess.java | ||
|---|---|---|
| 229 | 229 |
// w,h - width and height of the input texture. MVP - Model-View-Projection matrix to apply to the |
| 230 | 230 |
// texture; df - output FBO. |
| 231 | 231 |
|
| 232 |
synchronized void render(float w, float h, float[] mvp, DistortedFramebuffer df)
|
|
| 232 |
synchronized void render(float w, float h, float[] mvp, DistortedOutputSurface surface)
|
|
| 233 | 233 |
{
|
| 234 | 234 |
mBlurProgram.useProgram(); |
| 235 | 235 |
|
| 236 |
DistortedProjection inputP = mBufferFBO.getProjection(); |
|
| 237 |
DistortedProjection outputP = surface.getProjection(); |
|
| 238 |
|
|
| 236 | 239 |
int radius = (int)mUniforms[0]; |
| 237 | 240 |
if( radius>=MAX_BLUR ) radius = MAX_BLUR-1; |
| 238 | 241 |
computeGaussianKernel(radius); |
| ... | ... | |
| 252 | 255 |
GLES30.glViewport(0, 0, (int)w, (int)h); |
| 253 | 256 |
|
| 254 | 257 |
Matrix.setIdentityM(mTmpMatrix, 0); |
| 255 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -mBufferFBO.mDistance);
|
|
| 256 |
Matrix.multiplyMM(mMVPMatrix, 0, mBufferFBO.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 258 |
Matrix.translateM(mTmpMatrix, 0, 0, 0, -inputP.mDistance);
|
|
| 259 |
Matrix.multiplyMM(mMVPMatrix, 0, inputP.mProjectionMatrix, 0, mTmpMatrix, 0);
|
|
| 257 | 260 |
|
| 258 | 261 |
// horizontal blur |
| 259 | 262 |
GLES30.glUniform1fv( mOffsetsH ,radius+1, mOffsets,0); |
| ... | ... | |
| 263 | 266 |
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4); |
| 264 | 267 |
|
| 265 | 268 |
mBufferFBO.setAsInput(); |
| 266 |
df.setAsOutput(); |
|
| 267 |
GLES30.glViewport(0, 0, df.mWidth, df.mHeight); |
|
| 269 |
surface.setAsOutput(); |
|
| 270 |
|
|
| 271 |
GLES30.glViewport(0, 0, outputP.mWidth, outputP.mHeight); |
|
| 268 | 272 |
|
| 269 | 273 |
for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/w; |
| 270 | 274 |
|
Also available in: Unified diff
Major: change of API.
Split DFramebuffer into Framebuffer and Screen; introduce the 'DistortedInputSurface' and 'DistortedOutputSurface' interfaces.