Change imago to white and black

Started by Mr. K, April 18, 2016, 03:35:32 PM

Previous topic - Next topic

Mr. K

Hi guys
i want to change the color of the frameBuffer displayed, i mean  change the colors to white and black, there are a method for do this or i must use the convertion of pixels?

thanks  8)

EgonOlsen

This question is about the Android version, I assume?

Mr. K


EgonOlsen

If it has to be realtime (and just for a screenshot or similat), you have to write your own shaders. The simplest solution, would be to render the scene into an NPOTTexture (http://www.jpct.net/jpct-ae/doc/com/threed/jpct/NPOTTexture.html) with the size of the frame buffer instead of rendering it onto the frame buffer directly. Then, you would have to write a basic shader that just renders one texture layer without any lighting but averages the texture's colors to a grey scale output. Then assign this as a shader for blitting (http://www.jpct.net/jpct-ae/doc/com/threed/jpct/FrameBuffer.html#setBlittingShader(com.threed.jpct.GLSLShader)) and blit the texture that contains the rendered scene into the actual frame buffer.

Mr. K

No, isn't for a real time is for save a "screenshot" but i will try your advice  thanks a lot for the information :)

EgonOlsen

If it's just to save a screenshot, you can get away with simple bit-fiddling in the pixels array. That will be much easier than the real time approach.

Mr. K

#6
Can i get an example code for do the NPOTTexture and GLShader i can't understend how it works

EgonOlsen

You don't have to...really. If you want to do this more screen shots only, it's overkill. Just grab the pixels from the pixels array, extract the color compontents of each on, average them and write them back into the array. That's much easier.

Mr. K

Sorry i hope don't be annoying,  i did the convertion of pixels, but now i need to display on real time the image   :(

EgonOlsen

#9
I see. I don't have code lying around that does exactly that, but I'll try to hack some basic example. It may take some days though.

EgonOlsen

Here's a basic example. You need this new jar for it to run correctly: http://jpct.de/download/beta/jpct_ae.jar. It could be run with the old one as well, but it won't work as expected with this source code. You would have to add a kind of dummy blit to make it work with older versions, so it's better to use the new one. Anyway...here are the shaders:

vertex:
uniform mat4 modelViewProjectionMatrix;

uniform vec4 additionalColor;
uniform vec4 ambientColor;

uniform float alpha;
uniform bool useColors;

attribute vec4 position;
attribute vec3 normal;
attribute vec4 color;
attribute vec2 texture0;

varying vec2 texCoord;
varying vec4 vertexColor;

const vec4 WHITE = vec4(1,1,1,1);

void main() {
texCoord = texture0;

// Yes, these two lines actually serve no purpose...but if i remove them, my phone doesn't render anything using this shader...!?!? WTF?
vec4 pos = position;
vec3 normalDummy = normal;

vertexColor=vec4(min(WHITE, ambientColor + additionalColor).xyz, alpha);

if (useColors) {
vertexColor *= color;
}

gl_Position = modelViewProjectionMatrix * pos;
}


fragment:
precision highp float;

uniform sampler2D textureUnit0;

varying vec2 texCoord;
varying vec4 vertexColor;

void main() {

vec4 col=texture2D(textureUnit0, texCoord) * vertexColor;
float ca = (col.r + col.g + col.b)/3.0;
gl_FragColor=vec4(ca, ca, ca, col.a);
}



Example:
package com.example.blackwhite;

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

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

import com.threed.jpct.Camera;
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;

/**
* @author EgonOlsen
*
*/
public class BlackWhite extends Activity {

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

private int fps = 0;

private Light sun = null;

private RGBColor back = new RGBColor(50, 50, 10);

private Object3D obj;

private NPOTTexture offscreenBuffer = null;
private GLSLShader bwShader = null;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

mGLView = new GLSurfaceView(getApplication());
mGLView.setEGLContextClientVersion(2);
mGLView.setPreserveEGLContextOnPause(true);

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

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

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

@Override
protected void onStop() {
super.onStop();
System.exit(0);
}

protected boolean isFullscreenOpaque() {
return true;
}

class MyRenderer implements GLSurfaceView.Renderer {

private long time = System.currentTimeMillis();

public MyRenderer() {
}

public void onSurfaceChanged(GL10 gl, int w, int h) {

if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(w, h);
world = new World();
world.setAmbientLight(20, 20, 20);

try {
bwShader = new GLSLShader(Loader.loadTextFile(BlackWhite.this.getAssets().open("bwVertexShaderTex0Amb.src")), Loader.loadTextFile(BlackWhite.this.getAssets().open(
"bwFragmentShaderTex0Amb.src")));
} catch (Exception e) {
throw new RuntimeException(e);
}

sun = new Light(world);
sun.setIntensity(250, 250, 250);

TextureManager.getInstance().addTexture("texture", new Texture(16, 16, RGBColor.GREEN));
TextureManager.getInstance().addTexture("texture2", new Texture(16, 16, RGBColor.RED));
TextureManager.getInstance().addTexture("texture3", new Texture(16, 16, RGBColor.BLUE));

obj = Primitives.getSphere(20f);
world.addObject(obj);
obj.translate(0, 0, 0);
obj.setTexture("texture");
obj.build();

Object3D obj2 = Primitives.getSphere(15f);
world.addObject(obj2);
obj2.translate(40, -20, 0);
obj2.setTexture("texture2");
obj2.build();

Object3D obj3 = Primitives.getSphere(25f);
world.addObject(obj3);
obj3.translate(-70, 10, -10);
obj3.setTexture("texture3");
obj3.build();

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 150);
cam.lookAt(SimpleVector.ORIGIN);

SimpleVector sv = new SimpleVector();
sv.set(SimpleVector.ORIGIN);
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);

offscreenBuffer = new NPOTTexture(w, h, RGBColor.BLACK);
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//
}

public void onDrawFrame(GL10 gl) {
obj.rotateY(0.01f);

fb.setRenderTarget(offscreenBuffer);
fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();
fb.removeRenderTarget();

fb.setBlittingShader(bwShader);
fb.blit(offscreenBuffer, 0, 0, 0, fb.getHeight(), offscreenBuffer.getWidth(), offscreenBuffer.getHeight(), fb.getWidth(), -fb.getHeight(), -1, false);
fb.display();
fb.setBlittingShader(null);


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


What is basically does, is this:


  • render the scene as usual, but into a texture that serves as a back buffer
  • set a shader for blitting that converts color into b/w (done in the fragment shader, might need some tweaking)
  • blit the back buffer using the b/w shader

Mr. K

Thanks a lot Admin, this is what i want, really thanks