OpenGL ES 2.0 can't render to framebuffer object (FBO) on android -
i'm trying make finger drawing program android using xamarin (c#). got myself stuck problem regarding opengl. not quite it, have little experience directx (not mobile) not opengl.
so issue - i'm trying draw fbo created, thing seems work glclear() call. created framebuffer object , attached color texture it. have 2 shaders, 1 drawing framwbuffer itself, part works fine. other 1 simple make it.
vs: gl_position = a_position;
fs: gl_fragcolor = vec4(0.0f, 1.0f, 1.0f, 1.0f); //< sky blue
shader works ok, if use on screen, when try render onto framebuffer's color texture, nothing. tried different things turning off depth buffers explicitly. calling glflush(), glfinish() , on nothing seems work. framebuffer's texture affected glclear() statement. if don't clear see texture loaded on initialization. use same drawing routine , data (vertex buffer + index buffer) draw quads both rendering texture , rendering texture. position on screen alway kind of in center of screen (it takes values 0.5f vertex attributes in vbo). don't it. tested on real , virtual devices. results same. i'll paste code, mess.
class paintingview : androidgameview { public paintingview(context context, iattributeset attrs) : base(context, attrs) { init(); } public paintingview(intptr handle, android.runtime.jnihandleownership transfer) : base(handle, transfer) { init(); } private void init() { resize += delegate { gl.viewport(0, 0, _viewportwidth, _viewportheight); }; } protected override void onresize(eventargs e) { _viewportheight = height; _viewportwidth = width; makecurrent(); } protected override void createframebuffer() { contextrenderingapi = opentk.graphics.glversion.es2; try { base.createframebuffer(); return; } catch (exception ex) { } try { base.createframebuffer(); return; } catch (exception ex) { } throw new exception("can't load egl, aborting"); } protected override void onload(eventargs e) { base.onload(e); _viewportheight = height; _viewportwidth = width; _quadprogram = loadprogram(@" // uniform mat4 mvp_matrix; attribute vec4 a_position; attribute vec2 a_texcoord; varying vec2 v_texcoord; void main() { v_texcoord = a_texcoord; gl_position = a_position; //< mvp_matrix * a_position; } ", @" precision mediump float; uniform sampler2d u_texture; varying vec2 v_texcoord; void main() { gl_fragcolor = texture2d(u_texture, v_texcoord); } "); _simplequadprogram = loadprogram(@" attribute vec4 a_position; attribute vec2 a_texcoord; void main() { gl_position = a_position; } ", @" precision mediump float; void main() { gl_fragcolor = vec4(0.0f, 1.0f, 1.0f, 1.0f); //< sky blue } "); _uniform_texture = gl.getuniformlocation(_quadprogram, "u_texture"); _quadmodel = new quadmodel(1f, 0.5f); createoffscreentexture(); drawoffscreentexture(); run(); } private void createoffscreentexture() { gl.genframebuffers(1, out _framebufferid); gl.bindframebuffer(framebuffertarget.framebuffer, _framebufferid); _quadtexture = loadtexture(context, resource.drawable.testtexture); gl.framebuffertexture2d(framebuffertarget.framebuffer, framebufferslot.colorattachment0, texturetarget.texture2d, _quadtexture, 0); var status = gl.checkframebufferstatus(framebuffertarget.framebuffer); if (status != framebuffererrorcode.framebuffercomplete) throw new exception("frame buffer not complete"); gl.bindframebuffer(framebuffertarget.framebuffer, 0); } private void drawoffscreentexture() { gl.bindframebuffer(framebuffertarget.framebuffer, _framebufferid); gl.clearcolor(1f, 0f, 0f, 1f); gl.clear(clearbuffermask.colorbufferbit); // drawing nothing gl.useprogram(_simplequadprogram); _quadmodel.draw(); gl.bindtexture(texturetarget.texture2d, _quadtexture); gl.generatemipmap(texturetarget.texture2d); gl.bindframebuffer(framebuffertarget.framebuffer, 0); } private int loadprogram(string vertexshadersource, string fragmentshadersource) { int vertexshader = loadshader(shadertype.vertexshader, vertexshadersource); int fragmentshader = loadshader(shadertype.fragmentshader, fragmentshadersource); int resid = gl.createprogram(); if (resid == 0) throw new invalidoperationexception("unable create program"); gl.attachshader(resid, vertexshader); gl.attachshader(resid, fragmentshader); gl.bindattriblocation(resid, 0, "a_position"); gl.bindattriblocation(resid, 1, "a_texcoord"); gl.linkprogram(resid); int linked; gl.getprogram(resid, programparameter.linkstatus, out linked); if (linked == 0) { // link failed int length; gl.getprogram(resid, programparameter.infologlength, out length); if (length > 0) { var log = new stringbuilder(length); gl.getprograminfolog(resid, length, out length, log); log.debug("gl2", "couldn't link program: " + log.tostring()); } gl.deleteprogram(resid); throw new invalidoperationexception("unable link program"); } return resid; } private int loadtexture(context context, int resourceid) { int textureid = gl.gentexture(); gl.bindtexture(texturetarget.texture2d, textureid); gl.texparameter(texturetarget.texture2d, textureparametername.textureminfilter, (int)textureminfilter.linear); gl.texparameter(texturetarget.texture2d, textureparametername.texturemagfilter, (int)texturemagfilter.linear); gl.texparameter(texturetarget.texture2d, textureparametername.texturewraps, (int)texturewrapmode.repeat); gl.texparameter(texturetarget.texture2d, textureparametername.texturewrapt, (int)texturewrapmode.repeat); bitmap b = bitmapfactory.decoderesource(context.resources, resourceid); android.opengl.glutils.teximage2d((int)all.texture2d, 0, b, 0); b.recycle(); gl.generatemipmap(texturetarget.texture2d); return textureid; } private int loadshader(shadertype shadertype, string source) { int shader = gl.createshader(shadertype); if (shader == 0) throw new invalidoperationexception("unable create shader"); int length = 0; gl.shadersource(shader, 1, new string[] { source }, (int[])null); gl.compileshader(shader); int compiled; gl.getshader(shader, shaderparameter.compilestatus, out compiled); if (compiled == 0) { gl.getshader(shader, shaderparameter.infologlength, out length); if (length > 0) { var log = new stringbuilder(length); gl.getshaderinfolog(shader, length, out length, log); log.debug("gl2", "couldn't compile shader: " + log.tostring()); } gl.deleteshader(shader); throw new invalidoperationexception("unable compile shader of type : " + shadertype.tostring()); } return shader; } protected override void onrenderframe(frameeventargs e) { base.onrenderframe(e); gl.clearcolor(0.7f, 0.7f, 0.7f, 1); gl.clear(clearbuffermask.colorbufferbit); gl.useprogram(_quadprogram); gl.activetexture(textureunit.texture0); gl.bindtexture(texturetarget.texture2d, _quadtexture); gl.uniform1(_uniform_texture, 0); _quadmodel.draw(); swapbuffers(); } int _quadtexture; quadmodel _quadmodel; int _quadprogram; int _simplequadprogram; int _uniform_texture; int _framebufferid; int _viewportwidth, _viewportheight; } public class quadmodel { public quadmodel(float worldwidth, float worldheight) { // vertexposx, vertexposy, vertexposz, texcoordu, texcoordv float[] vertexbufferdata = { 0, 0, 0, 0, 1, worldwidth, 0, 0, 1, 1, worldwidth, worldheight, 0, 1, 0, 0, worldheight, 0, 0, 0, }; ushort[] indexbufferdata = { 0, 1, 2, 2, 3, 0, }; gl.genbuffers(1, out _vertexbufferid); gl.bindbuffer(buffertarget.arraybuffer, _vertexbufferid); gl.bufferdata(buffertarget.arraybuffer, (intptr)(vertexbufferdata.length * sizeof(float)), vertexbufferdata, bufferusage.staticdraw); gl.bindbuffer(buffertarget.arraybuffer, 0); gl.genbuffers(1, out _indexbufferid); gl.bindbuffer(buffertarget.elementarraybuffer, _indexbufferid); gl.bufferdata(buffertarget.elementarraybuffer, (intptr)(indexbufferdata.length * sizeof(ushort)), indexbufferdata, bufferusage.staticdraw); gl.bindbuffer(buffertarget.elementarraybuffer, 0); } public void draw() { const int vertexpositionidx = 0; const int texcoordidx = 1; gl.bindbuffer(buffertarget.arraybuffer, _vertexbufferid); gl.vertexattribpointer(vertexpositionidx, 2, vertexattribpointertype.float, false, sizeof(float) * 5, intptr.zero); gl.enablevertexattribarray(vertexpositionidx); gl.vertexattribpointer(texcoordidx, 2, vertexattribpointertype.float, false, sizeof(float) * 5, new intptr(sizeof(float) * 3)); gl.enablevertexattribarray(texcoordidx); gl.bindbuffer(buffertarget.elementarraybuffer, _indexbufferid); gl.drawelements(beginmode.triangles, 6, drawelementstype.unsignedshort, intptr.zero); gl.bindbuffer(buffertarget.arraybuffer, 0); gl.bindbuffer(buffertarget.elementarraybuffer, 0); } private int _vertexbufferid; private int _indexbufferid; }
edit: tried use glviewort size of rendertexture right after binding fbo, drawing works coordinates wrong (clearly not set in vertex data still quad). looks drawing time, bigger viewport set, bigger , farther right bottom side appears quad. in case of viewport = screen size drew out of framebuffer object's visible area. i'll figure out relation viewport size later.
Comments
Post a Comment