Main Menu

Shaders

Started by Geemili, June 25, 2012, 06:34:38 PM

Previous topic - Next topic

Geemili

Hi, this is my first time venturing into 3D and am trying to use shaders. Specifically, outlining and cel-shading. I have made the cel-shading following some tutorials, but cannot figure out the outlining.

I have found two ways of doing outlining, the first is editing the rendered image and applying a sobel filter or another of similar effect. When I tried doing this, I didn't get it to work, but it required me to use FrameBuffer.getPixels(), which seems to be slow. Also, my fault here, I don't understand the images format, at least, not enough to change into a 2d array of colors.

The second way is to first draw a wireframe version of the current object with its front faces culled and the rendering it regularly. This one is supposedly easier, but I don't know where to place the code.

Also, less important (In My Opinion) is how to get the lightVec variable to glsl. I saw it used in the shader example and put:
varying vec3 lightVec
into the .glsl, but it did not seem to work.

Thank for reading my post. I am sorry for any ignorance, but I feel impatient to get this done. Ask if you need code.

Thomas.

For variables in shader you have to use uniforms. Varying is used to interpolation variables from vertex shader to fragment shader.
So in application you should use "shader.setUniform("lightVec", ...);" and in shader "uniform vec3 lightVec;"...

EgonOlsen

Quote from: Geemili on June 25, 2012, 06:34:38 PM
The second way is to first draw a wireframe version of the current object with its front faces culled and the rendering it regularly. This one is supposedly easier, but I don't know where to place the code.
Can you explain this in a little more detail. I'm not 100% sure that i get the idea...

Geemili

Sorry, I'm not the best at explaining. Here is a link that should help. You'll have to scroll down a bit though, it's in section 3.4.

EgonOlsen

I see...to do this with jPCT's wireframe rendering mode, you have to implement a simple IRenderHook to tweak it, because by default, jPCT uses a line width of 1 and no culling in wireframe mode. Here's a little example....however, i don't really think that the effect looks that great in motion...anyway...


import java.awt.Color;

import org.lwjgl.opengl.GL11;

import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderHook;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Loader;
import com.threed.jpct.Object3D;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;

public class Outlines {

private World world;

private FrameBuffer buffer;

private Object3D box;

public static void main(String[] args) throws Exception {
new Outlines().loop();
}

public Outlines() throws Exception {
world = new World();
world.setAmbientLight(255, 255, 255);

TextureManager.getInstance().addTexture("box", new Texture("box.jpg"));

box = Loader.loadASC("beethoven.asc", 50f, false);
box.setTexture("box");
box.rotateX((float) Math.PI / 2f);
box.rotateMesh();
box.clearRotation();
box.calcTextureWrapSpherical();
box.build();
box.compile();
world.addObject(box);

world.getCamera().setPosition(50, 20, -5);
world.getCamera().lookAt(box.getTransformedCenter());
}

private void loop() throws Exception {
buffer = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_GL_AA_2X);
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
buffer.enableRenderer(IRenderer.RENDERER_OPENGL);

Outliner ol=new Outliner();

while (!org.lwjgl.opengl.Display.isCloseRequested()) {
box.rotateY(0.01f);
box.rotateX(0.01f);
buffer.clear(java.awt.Color.BLUE);


box.invertCulling(true);
box.setRenderHook(ol);
world.renderScene(buffer);
world.drawWireframe(buffer, Color.BLACK);
box.setRenderHook(null);

box.invertCulling(false);
world.renderScene(buffer);
world.draw(buffer);

buffer.update();
buffer.displayGLOnly();

Thread.sleep(10);
}
buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
buffer.dispose();
System.exit(0);
}

private static class Outliner implements IRenderHook {

@Override
public void beforeRendering(int polyID) {
GL11.glLineWidth(5);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glEnable(GL11.GL_CULL_FACE);
}

@Override
public void afterRendering(int polyID) {
GL11.glLineWidth(1);
}

@Override
public void setCurrentObject3D(Object3D obj) {
// TODO Auto-generated method stub
}

@Override
public void setTransparency(float transparency) {
// TODO Auto-generated method stub

}

@Override
public void onDispose() {
// TODO Auto-generated method stub

}

@Override
public boolean repeatRendering() {
// TODO Auto-generated method stub
return false;
}

@Override
public void clear() {
// TODO Auto-generated method stub

}

}
}


Geemili

Thank you! It works perfectly!  ;D

The only major change that will need to be done is something that does it automatically for each object, which shouldn't be so bad. Thanks again!