OpenGL-渲染到纹理 - 整个渲染场景

时间:2015-08-03 06:21:10

标签: android opengl-es

我在OpenGL游戏中实现了FBO。并且我渲染渲染到屏幕的纹理,问题是渲染到纹理从左下角开始。看:

呈现给默认帧缓冲区的内容:

enter image description here

渲染到附加到FBO的纹理的内容:

enter image description here

但我想要渲染到纹理的地方是:

enter image description here

我计算了假设矩形(红点)位置。但我不知道如何准确渲染该区域,

我该怎么做?这里是渲染器Calass(FBO操作在onDrawFrame函数中完成):

public class CurlRenderer implements GLSurfaceView.Renderer {

// Constant for requesting right page rect.
public static final int PAGE = 1;
// Set to true for checking quickly how perspective projection looks.
private static final boolean USE_PERSPECTIVE_PROJECTION = false;
// Background fill color.
private int mBackgroundColor;
// Curl meshes used for static and dynamic rendering.
private CurlMesh mCurlMesh;
private RectF mMargins = new RectF();
private CurlRenderer.Observer mObserver;
// Page rectangles.
private RectF mPageRect;
// View mode.
// Screen size.
private int mViewportWidth, mViewportHeight;
// Rect for render area.
private RectF mViewRect = new RectF();
private boolean first = true;
int[] fb, renderTex; 
int texW = 300; 
int texH = 256; 
IntBuffer texBuffer;
int[] buf = new int[texW * texH];
GL11ExtensionPack gl11ep ;
/**
 * Basic constructor.
 */
public CurlRenderer(CurlRenderer.Observer observer) {
    mObserver = observer;
    mCurlMesh = new CurlMesh(0);
    mPageRect = new RectF();
}

/**
 * Adds CurlMesh to this renderer.
 */
public synchronized void addCurlMesh(CurlMesh mesh) {
    mCurlMesh = mesh;
}

/**
 * Returns rect reserved for left or right page. Value page should be
 * PAGE_LEFT or PAGE_RIGHT.
 */
public RectF getPageRect(int page) {
        if (page == PAGE) {
        return mPageRect;
    }
    return null;
}
public void setup(GL10 gl){
    fb = new int[1];
    renderTex = new int[1];
    // generate
    ((GL11ExtensionPack)gl).glGenFramebuffersOES(1, fb, 0); 
    gl.glEnable(GL10.GL_TEXTURE_2D);
    gl.glGenTextures(1, renderTex, 0);// generate texture
    gl.glBindTexture(GL10.GL_TEXTURE_2D, renderTex[0]);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
   // texBuffer = ByteBuffer.allocateDirect(buf.length*4).order(ByteOrder.nativeOrder()).asIntBuffer();
   // gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,GL10.GL_MODULATE);
    gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, texW, texH, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_SHORT_4_4_4_4, null);
    gl.glDisable(GL10.GL_TEXTURE_2D);
}
boolean RenderStart(GL10 gl){
    // Bind the framebuffer
    ((GL11ExtensionPack)gl).glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, fb[0]);

    // specify texture as color attachment
    ((GL11ExtensionPack)gl).glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, renderTex[0], 0);


    int error = gl.glGetError();
    if (error != GL10.GL_NO_ERROR) {
        Log.d("err", "Background Load GLError: " + error+"      ");
    }
    int status = ((GL11ExtensionPack)gl).glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES);
    if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES)
    {
        Log.d("err", "Background Load GLError: " + status+"      ");;
        return true;
    }
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    return true;
}
void RenderEnd(GL10 gl){
    ((GL11ExtensionPack)gl).glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0);

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

    gl.glEnable(GL10.GL_TEXTURE_2D);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, renderTex[0]);
    gl.glColor4f(1,1,1,1);
    gl.glDisable(GL10.GL_TEXTURE_2D);
}

@Override
public synchronized void onDrawFrame(GL10 gl) {
    if(first){
    int h = GLES20.glGetError();
    this.setup(gl);
    if(h!=0){
        Log.d("ERROR", "ERROR Happend"+h+"");
    }
    first = false;
    }
    mObserver.onDrawFrame();
    //glClearColor miad rangi ke maa entekhaab kardim ro tooye carde Graphic register mikone
    gl.glClearColor(Color.red(mBackgroundColor) / 255f,
            Color.green(mBackgroundColor) / 255f,
            Color.blue(mBackgroundColor) / 255f,
            Color.alpha(mBackgroundColor) / 255f);
    //glClear miad oon rangi ke bala register karde boodim ro dige az buffer paak mikone
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    //miad matris ro be MabdaEsh barmigardoone, ke bAd baraye glRotate va glTranslate moshkeli ijaad nashe
    //chon maa asle jaabejaa kardan hamoon baraye safhe, baste be makaane avalieye
    // kaaghazemoon hast, na oon makani ke dar haale hazer gharaar dare
    gl.glLoadIdentity();

    if (USE_PERSPECTIVE_PROJECTION) {
        gl.glTranslatef(0, 0, -6f);
    }


    RenderStart(gl);
    mCurlMesh.onDrawFrame(gl);
    RenderEnd(gl);
    mCurlMesh.onDrawFrame(gl);

}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    gl.glViewport(0, 0, width, height);
    mViewportWidth = width;
    mViewportHeight = height;

    float ratio = (float) width / height;
    mViewRect.top = 1.0f;
    mViewRect.bottom = -1.0f;
    mViewRect.left = -ratio;
    mViewRect.right = ratio;
    updatePageRects();

    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    if (USE_PERSPECTIVE_PROJECTION) {
        GLU.gluPerspective(gl, 20f, (float) width / height, .1f, 100f);
    } else {
        GLU.gluOrtho2D(gl, mViewRect.left, mViewRect.right,
                mViewRect.bottom, mViewRect.top);
    }

    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//  mCurlMesh.setup(gl);
    gl.glClearColor(0f, 0f, 0f, 1f);
    gl.glShadeModel(GL10.GL_SMOOTH);
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    gl.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST);
    //gl.glHint(GL10.GL_POLYGON_SMOOTH_HINT, GL10.GL_NICEST);
    gl.glEnable(GL10.GL_LINE_SMOOTH);
    gl.glDisable(GL10.GL_DEPTH_TEST);
    gl.glDisable(GL10.GL_CULL_FACE);
}


/**
 * Change background/clear color.
 */
public void setBackgroundColor(int color) {
    mBackgroundColor = color;
}

/**
 * Set margins or padding. Note: margins are proportional. Meaning a value
 * of .1f will produce a 10% margin.
 */
public synchronized void setMargins(float left, float top, float right,
        float bottom) {
    mMargins.left = left;
    mMargins.top = top;
    mMargins.right = right;
    mMargins.bottom = bottom;
    updatePageRects();
}
/**
 * Translates screen coordinates into view coordinates.
 * mokhtassate ye noghte (masalan pointer Position) roye safhe ro, be moAdele mokhtasaatesh
 * rooye CurlView Tabdil mikene
 */
public void translate(PointF pt) {
    pt.x = mViewRect.left + (mViewRect.width() * pt.x / mViewportWidth);
    pt.y = mViewRect.top - (-mViewRect.height() * pt.y / mViewportHeight);
}

/**
 * Recalculates page rectangles.
 */
private void updatePageRects() {
    if (mViewRect.width() == 0 || mViewRect.height() == 0) {
        return;
    }
    /**
     * @ TODO inja daghighan hamnoon kaari ke mikham, yAni size dadan be Page ro anjaam mide
     * mpageRect... khode meshe  va mViewRect view E layout
     */
        mPageRect.set(mViewRect);
        mPageRect.left += mViewRect.width() * mMargins.left;
        mPageRect.right -= mViewRect.width() * mMargins.right;
        mPageRect.top += mViewRect.height() * mMargins.top;
        mPageRect.bottom -= mViewRect.height() * mMargins.bottom;

        int bitmapW = (int) ((mPageRect.width() * mViewportWidth) / mViewRect.width());
        int bitmapH = (int) ((mPageRect.height() * mViewportHeight) / mViewRect.height());
        mObserver.onPageSizeChanged(bitmapW, bitmapH);

}

/**
 * Observer for waiting render engine/state updates.
 */
public interface Observer {
    /**
     * Called from onDrawFrame called before rendering is started. This is
     * intended to be used for animation purposes.
     */
    public void onDrawFrame();

    /**
     * Called once page size is changed. Width and height tell the page size
     * in pixels making it possible to update textures accordingly.
     */
    public void onPageSizeChanged(int width, int height);

     }
} 

1 个答案:

答案 0 :(得分:1)

首先,您应该了解基本的渲染管道。其中,在乘以投影矩阵之后存在剪切坐标。当你调用gluOrtho2D()这是投影矩阵时,你自己剪切对象。

简而言之,RTT(渲染到纹理)只是渲染到渲染目标(FBO)的纹理,并且您在FBO处绘制了切碎的三角形,因此您可以获得不希望获得的切割纹理。

在框中绘制对象是在乘以投影之后和在w分割步骤之后,所有x,y,范围必须在[-1,1]之间。如果很难为你计算,不要将投影矩阵与相乘,确保所有x,y和z值都在[-1,1]范围内,W必须为1