我在我的 OpenGL 游戏上实现了 FBO。我将渲染到屏幕的内容渲染为纹理,问题是渲染到纹理是从左下角开始的。看:
渲染到默认帧缓冲区的内容:
附加到 FBO 的纹理渲染了什么:
但我想要渲染到纹理的地方是:
我怎样才能做到这一点?这里是渲染器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);
}
}
Run Code Online (Sandbox Code Playgroud)
您缺少设置 FBO 渲染的视口。如果您只想绘制与绘制到默认帧缓冲区相同的几何体部分,则可以使用纹理大小作为视口尺寸:
glViewport(0, 0, texW, texH);
Run Code Online (Sandbox Code Playgroud)
完成 FBO 渲染后,不要忘记将视口设置回视图/表面的适当大小,并再次开始渲染到默认帧缓冲区。
要绘制几何体的不同(子)部分,如草图中所示,您有以下几种选择:
使用其中任何一个的结果可能略有不同,具体取决于渲染内容和渲染方式。特别是如果涉及照明或透视投影,并非所有选项都会给出完全相同的结果。在这种情况下,您必须决定您想要哪种行为。
更改其中一种转换可能是最标准的方法。但调整视口可能是一个优雅的选择,具体取决于您想要实现的目标。
例如,只是根据草图粗略地猜测值,您可以使用:
glViewport(texW / 4, -texH / 4, texW / 2, texH);
Run Code Online (Sandbox Code Playgroud)
这定义了视口矩形以大致匹配草图中的橙色虚线矩形。您可能需要对这些值进行更多数学计算才能保持纵横比,但这显示了基本思想。
| 归档时间: |
|
| 查看次数: |
1909 次 |
| 最近记录: |