Depth buffer texture

Started by Thomas., June 30, 2012, 01:58:21 AM

Previous topic - Next topic

EgonOlsen

#75
It's the exact same method with the only difference that one sets the flag to clean the depth buffer in addition to the color buffer and the other one doesn't.

EgonOlsen

#76
Quote from: Thomas. on July 12, 2012, 12:47:07 AM
It is same on my phone :(
Is that so? I thought that on your phone, depth is correct and colors are wrong? On mine, it's the opposite.

...maybe these chips are optimizing away the depth buffer output or something like this so that the render buffer doesn't get filled at all. According to the documentation from PowerVR, this shouldn't be the case, but you never know. The chip itself doesn't need a zbuffer at all because it does it all internally.

Thomas.

In my test app on my device is immediately after start, and if I rotate teapot, first rendering fine like layer under bad colored rendering, depth working?, second rendering is fine. After a while (max 1sec) is first "fine rendering" gone, depth working and also second rendering working.



Is there any other solution to preserve the depth buffer?

EgonOlsen

#78
Judging from the screen shot, your depth buffer never gets cleared (that's why everything is green...it simply doesn't render anything with equal or higher depth at these parts so that the background color is visible)...in comparison to mine, which gets cleared for each render (or never filled...i don't know). I'll add some debug code later today to see, if i've some flaw in the buffer handling. But if not, i would say that it simply doesn't work on current drivers at least for these two architectures.

Thomas.

#79
I did some testing...
This code show green and also shaded teapot and blinking green/shaded. On screen shot is not visible.
fb.clear();
fb.setRenderTarget(renderTarget);
fb.clear();
world.renderScene(fb);
world.draw(fb);
fb.display();
fb.removeRenderTarget();

fb.setRenderTarget(renderTarget2);
fb.clearColorBufferOnly(RGBColor.GREEN);
secWorld.renderScene(fb);
secWorld.draw(fb);
fb.display();
fb.clearZBufferOnly();
fb.removeRenderTarget();


When I press home button and back to app, first and second rendering are fine, but depth buffer doesn't work.
What stencil buffer? Can it collide with depth?

Thomas.

#80
What differences are among SDK and native code for controlling GPU? In native somehow working sharing depth buffer. I thing that it is used in Nova2 and Nova3.

Left effect (distortion image) can not be done without depth buffer (I think, it is not true, it is excellent, say me how :) ). And it is fast, I played it on Galaxy S.

EgonOlsen

I've no idea what they are doing as i've no idea what strange ways might exist to create that effect...and i actually don't care, to be honest. I'm trying to get this depth buffer sharing working because i think it's a useful feature, but if it doesn't work out, i'll disable it and leave it for now. Too much time has already been spend on this IMHO...

Thomas.

For me it is important, it allows a lot of effects. I can also check depth myself (from depth buffer texture, that is needed for depth of field) but it needs condition and will be slow... so I accept any other solution.

EgonOlsen

Quote from: Thomas. on July 12, 2012, 10:53:49 PM
For me it is important, it allows a lot of effects.
I know...that's the only reason why i'm still bothering with it...i've spend the whole evening trying all kinds of things and reading a lot of stuff. I've also modified your test case to get rid of the Overlay and make depth buffer usage more obvious...but on my phone, it all comes down to: The second render pass doesn't use the depth data from the first render pass. It always starts off with an empty depth buffer no matter what i do. It even does this, if i don't bind the render buffer for the depth at all...just because the PowerVRs actually don't need a depth buffer. IMHO, the driver doesn't give a rat's ass about this buffer and it pretty happy with the internal buffer.

EgonOlsen

I've updated the jar again with latest version. It still doesn't work on my phone, but for the sake of completeness, please give it a try. I don't even know anymore if it really differs from the last one after reverting all my pointless tries...at least it has more debug log output if you enable that.

This is the modified test case that i was using:


package cz.chladek.shadertest;

import java.lang.reflect.Field;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;

import com.threed.jpct.Camera;
import com.threed.jpct.Config;
import com.threed.jpct.DepthBuffer;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.GLSLShader;
import com.threed.jpct.Light;
import com.threed.jpct.Loader;
import com.threed.jpct.Logger;
import com.threed.jpct.NPOTTexture;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;

public class ShaderTest extends Activity {

// Used to handle pause and resume...
private static ShaderTest master = null;

private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;

private World secWorld;

private World dummyWorld=new World();

private float touchTurn = 0;
private float touchTurnUp = 0;

private float xpos = -1;
private float ypos = -1;

private Texture font = null;

private Object3D[] objects;
private Light light;

private int selectedObject;

private Texture renderTarget;
private Texture renderTarget2;

protected void onCreate(Bundle savedInstanceState) {
Logger.log("onCreate");
//Logger.setLogLevel(Logger.LL_DEBUG);

Logger.setLogLevel(Logger.LL_DEBUG);

requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);

if (master != null) {
copy(master);
}

super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());

// Enable the OpenGL ES2.0 context
mGLView.setEGLContextClientVersion(2);

renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
}

@Override
protected void onPause() {
Logger.log("onPause");
super.onPause();
mGLView.onPause();
}

@Override
protected void onResume() {
Logger.log("onResume");
super.onResume();
mGLView.onResume();
}

@Override
protected void onStop() {
Logger.log("onStop");
super.onStop();
}

private void copy(Object src) {
try {
Logger.log("Copying data from master Activity!");
Field[] fs = src.getClass().getDeclaredFields();
for (Field f : fs) {
f.setAccessible(true);
f.set(this, f.get(src));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
return true;
}

if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;

xpos = me.getX();
ypos = me.getY();

touchTurn = xd / -100f;
touchTurnUp = yd / -100f;
return true;
}

try {
Thread.sleep(15);
} catch (Exception e) {
// No need for this...
}

return super.onTouchEvent(me);
}

public boolean onKeyDown(int keyCode, KeyEvent msg) {

if (keyCode == KeyEvent.KEYCODE_MENU) {
selectedObject = (selectedObject + 1 == objects.length) ? 0 : selectedObject + 1;
renderer.showObjectIndex(selectedObject);
return true;
}

return super.onKeyDown(keyCode, msg);
}

protected boolean isFullscreenOpaque() {
return true;
}

class MyRenderer implements GLSurfaceView.Renderer {

private int fps = 0;
private int lfps = 0;

private long time = System.currentTimeMillis();

private Resources res;
private GLSLShader pointLightShader;
private TextureManager tm;

public MyRenderer() {
Config.farPlane = 2000;
Config.useNormalsFromOBJ = true;
Texture.defaultToMipmapping(true);
Texture.defaultTo4bpp(true);
}

public void onSurfaceChanged(GL10 gl, int w, int h) {
if (fb != null)
fb.dispose();

fb = new FrameBuffer(w, h);

if (master == null) {
world = new World();
res = getResources();
tm = TextureManager.getInstance();

font = new Texture(res.openRawResource(R.raw.numbers));
font.setMipmap(false);

pointLightShader = new GLSLShader(Loader.loadTextFile(res.openRawResource(R.raw.pixel_light_vertex)),
Loader.loadTextFile(res.openRawResource(R.raw.pixel_light_fragment_1)));

loadObjects();

light = new Light(world);
light.setIntensity(50, 50, 50);
light.setPosition(new SimpleVector(0, 0, -10));

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 3);
cam.lookAt(objects[selectedObject].getTransformedCenter());

Object3D sp=Primitives.getSphere(2);
sp.translate(-2, 0, 0);
world.addObject(sp);

world.setAmbientLight(100, 100, 100);
world.compileAllObjects();

renderTarget = new NPOTTexture(fb.getWidth(), fb.getHeight(), null);
tm.addTexture("renderTarget", renderTarget);

renderTarget2 = new NPOTTexture(fb.getWidth(), fb.getHeight(), null);
tm.addTexture("renderTarget2", renderTarget2);

DepthBuffer depthBuffer = new DepthBuffer(fb.getWidth(), fb.getHeight());
renderTarget.setDepthBuffer(depthBuffer);
renderTarget2.setDepthBuffer(depthBuffer);

secWorld = new World();

Object3D sp2=Primitives.getSphere(2);
sp2.translate(2, 0, 0);
secWorld.addObject(sp2);

Object3D plane = Primitives.getPlane(1, 2f);
plane.setAdditionalColor(RGBColor.BLUE);
plane.rotateX(0.5f);
plane.build();
secWorld.addObject(plane);
secWorld.getCamera().moveCamera(Camera.CAMERA_MOVEOUT, 3);

if (master == null) {
Logger.log("Saving master Activity!");
master = ShaderTest.this;
}
}
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Logger.log("onSurfaceCreated");
}

public void loadObjects() {
world.removeAllObjects();

objects = new Object3D[1];
objects[0] = Loader.loadOBJ(res.openRawResource(R.raw.box_o), res.openRawResource(R.raw.box_m), 1.5f)[0];
/*
objects[1] = Loader.loadOBJ(res.openRawResource(R.raw.plane_o), res.openRawResource(R.raw.plane_m), 2)[0];
objects[2] = Loader.loadOBJ(res.openRawResource(R.raw.teapot_o), res.openRawResource(R.raw.teapot_m), 2)[0];
objects[3] = Loader.loadOBJ(res.openRawResource(R.raw.airplane_o), res.openRawResource(R.raw.airplane_m), 0.013f)[0];
objects[4] = Loader.loadOBJ(res.openRawResource(R.raw.car_o), res.openRawResource(R.raw.car_m), 0.02f)[0];
objects[5] = Loader.loadOBJ(res.openRawResource(R.raw.car2_o), res.openRawResource(R.raw.car2_m), 0.03f)[0];
*/
for (Object3D object : objects)
object.setShader(pointLightShader);

showObjectIndex(selectedObject);

world.addObjects(objects);
}

public void showObjectIndex(int index) {
for (int i = 0; i < objects.length; i++)
if (i != index)
objects[i].setVisibility(false);
else
objects[i].setVisibility(true);
}

public void onDrawFrame(GL10 gl) {
if (touchTurn != 0) {
objects[selectedObject].rotateY(touchTurn);
touchTurn = 0;
}

if (touchTurnUp != 0) {
objects[selectedObject].rotateX(touchTurnUp);
touchTurnUp = 0;
}

fb.setRenderTarget(renderTarget);
fb.clear(RGBColor.RED);
world.renderScene(fb);
world.draw(fb);
fb.display();
fb.removeRenderTarget();

fb.setRenderTarget(renderTarget2);
fb.blit(renderTarget, 0, 0, 0, 0, fb.getWidth(), fb.getHeight(), FrameBuffer.OPAQUE_BLITTING);
secWorld.renderScene(fb);
secWorld.draw(fb);
fb.display();
fb.removeRenderTarget();

fb.blit(renderTarget2, 0, 0, 0, 0, fb.getWidth(), fb.getHeight(), FrameBuffer.OPAQUE_BLITTING);

blitNumber(lfps, 5, 5);
fb.display();

if (System.currentTimeMillis() - time >= 1000) {
lfps = fps;
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}

private void blitNumber(float number, int x, int y) {
if (font != null) {
String sNum = Float.toString(number);

for (int i = 0; i < sNum.length(); i++) {
char cNum = sNum.charAt(i);
int iNum = cNum - 48;
fb.blit(font, iNum * 5, 0, x, y, 5, 9, 5, 9, 10, true, null);
x += 5;
}
}
}
}
}


Thomas.

#85
I see that blit is working when is rendered to target, now. Texture from render to target is flipped. When I fixed it, first render is fine, second render is find, depth is fine :) but... When I'm rotating a object in second rendering, object's blinking (rotating a object in first one is fine).

With this code are everything OK, but blinks part of second object, that should be hidden (discard by depth buffer).
fb.setRenderTarget(renderTarget);
fb.clear();
world.renderScene(fb);
world.draw(fb);
fb.display();
fb.removeRenderTarget();

fb.setRenderTarget(renderTarget2);
fb.blit(renderTarget, 0, 0, 0, fb.getHeight(), fb.getWidth(), fb.getHeight(), fb.getWidth(), -fb.getHeight(), -1, false, null);
secWorld.renderScene(fb);
secWorld.draw(fb);
fb.display();
fb.clearZBufferOnly();
fb.removeRenderTarget();

fb.blit(renderTarget2, 0, 0, 0, fb.getHeight(), fb.getWidth(), fb.getHeight(), fb.getWidth(), -fb.getHeight(), -1, false, null);


I know, you got sick of preservation depth, but is there any chance to fix blinking? And is it all right on your device, when you flip texture from the rendering?

EgonOlsen

Can you catch this blinking in some screen shots? Just to get a feel for this. I'll try at home with correct blitting, but i'm 99.999999999% sure that it won't help anything. My phone simply resists to write depth into that buffer or clears it each time it gets bound (which is documented behaviour for the FIRST bind...too bad that the specs say nothing about subsequent binds...).

Thomas.

Good news, on xperia neo is everything fine. In screenshot is not visible blinking, I took video. When thread is slept for some milliseconds, blinking are gone.

Teapot is in the first render, plane in the second. After 15 second in video, I'm clearing depth buffer in second rendering after is  displayed frame buffer.
http://youtu.be/XtpX2eDIY6A

Log
07-13 13:56:40.094: I/jPCT-AE(23604): Binding buffers (1/1)!
07-13 13:56:40.094: I/jPCT-AE(23604): Unbinding buffers (1)!
07-13 13:56:40.094: I/jPCT-AE(23604): Binding buffers (2/1)!
07-13 13:56:40.094: I/jPCT-AE(23604): Unbinding buffers (2)!

EgonOlsen

...it didn't help anything...as expected. I did some further testing and it is pretty obvious: On my device, the depth buffer somehow gets clear each time i bind the render buffer. This is not supposed to happen, but it does...and i have no idea how to prevent this. I consider it to be a driver bug or at least a weak spot of the GL specs. Because the docs state that this happens for the first bind but don't make any predicates about subsequent binds.

Your video is strange too. It shows some artifacts, but i'm not sure if they come from the rendering or a faulty video compression. If you delay the frames (i.e. add a long sleep at the end), is the image correct at the end of the frame, i.e. does the flickering happen during the rendering process or does it happen because different final frames show different results?
Have you tried if it changes something if you omit the inbetween call to removeRenderTarget(), i.e. simply replace the first with the second?

Thomas.

#89
Lighter lines is bad video compression (from xperia neo), blinking part of red plane is fault, that I want to show. If I delay the frame (20 millis) and use blit method, all is well (correct rendering, no blinking).
Plane is blinking (if object is rotated), when I blit texture from first rendering in second rendering in full resolution. I set in blit method, that source width and height are half and it is fine.
When plane is blinking, it seems like first texture is showed on screen and after little delayed second texture with artefacts. With delayed frames this doesn't happened.
When I use overlay, texture from first rendering is black (from clear color buffer), but depth working. When I'm rotating objects, teapot is correct, but little bit rotated and like layer under black teapot. So, black or correct teapot is one frame delayed...

Quote from: EgonOlsen on July 13, 2012, 09:42:12 PM
Have you tried if it changes something if you omit the inbetween call to removeRenderTarget(), i.e. simply replace the first with the second?

Nothing happened (some as before)

Is there possibility for send mail to ARM and ask for help?