我在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);
}
}
答案 0 :(得分:1)
首先,您应该了解基本的渲染管道。其中,在乘以投影矩阵之后存在剪切坐标。当你调用gluOrtho2D()这是投影矩阵时,你自己剪切对象。
简而言之,RTT(渲染到纹理)只是渲染到渲染目标(FBO)的纹理,并且您在FBO处绘制了切碎的三角形,因此您可以获得不希望获得的切割纹理。
在框中绘制对象是在乘以投影之后和在w分割步骤之后,所有x,y,范围必须在[-1,1]之间。如果很难为你计算,不要将投影矩阵与相乘,确保所有x,y和z值都在[-1,1]范围内,W必须为1