# Gaussblur Shader



## javaPanther (14. Dez 2011)

Hallo liebe Leute,
diesmal habe ich (hoffentlich) nur eine kleine Frage bzgl der Intesität innerhalb eines Shaders. Hierfür habe ich den Code aus dem Tutorial übernommen: 

Game Rendering  Gaussian Blur Filter Shader


Ich würde zusätzlich gerne einen Effekt erzielen mit dessen Hilfe man fließend von Scharf auf unscharf stellen kann, quasi den Fokus vom Vordergrund auf den Hintergrund verschieben. Wenn hierzu ANregungen oder sogar Lösungen existieren würde ich mich ebenfalls sehr darüber freuen 

1000 und einen Dank sowie Grüße im Voraus!


----------



## Guest2 (14. Dez 2011)

Moin,

das aus dem Beispiel ist ein ganz normaler Box-Filter, bei dem der Farbwert aus einem gewichteten Mittel (mehr oder weniger Gauss) aus einer 9x9 Matrix bestimmt wird (in zwei Schritten). Die Stärke des Effekts hängt von der Gewichtung ab (die 0.05 – 0.16) wenn Du die Gewichtung verschiebst (mehr Richtung Mitte / die Summe sollte trotzdem 1 bleiben), wird der "Unschärfekreis" kleiner und der Effekt schwächer (das ist dann zwar vermutlich kein Gauss mehr, aber optisch sollte das nicht stören). Damit das flexibel ist, solltest Du dazu eine zusätzliche uniforme Variable einführen.

Aber, das Ganze ist "nur" ein Weichzeichner, dabei wird immer alles gleich weich gezeichnet. Beim Fokus hängt die Unschärfe aber von der Entfernung ab. Deshalb können auf einem Bild gleichzeitig scharfe und unscharfe Objekte abgebildet werden. Das zu realisieren ist eine ganze Ecke schwieriger. Ein Beispiel dazu liefert GPU Gems 3: Chapter 28. Practical Post-Process Depth of Field.

Viele Grüße,
Fancy


----------



## javaPanther (15. Dez 2011)

Hi und danke für den ersten Ansatz.
Die Unschärfe findet lediglich auf 2 Dimensionaler Ebene innerhalb einer Skybox mit einer dhinterliegenden Skybox statt. In der Vorderen befinden sich z.B. Wände und Türen, während sich in der Hinteren die nächsten Räume befinden. Wenn man nun durch eine Tür auf die hintere Skybox blickt, soll diese auf scharf gestellt werden und die Vordere unscharf und umgekehrt.

Für diesen Zweck habe ich die Klasse + Methode eingebaut:

```
package shaders;

import org.lwjgl.opengl.GL20;


public class GaussBlur extends Shader{

	public float blurSize = 512.0f;
	public float[] layer = new float[]{0.05f, 0.06f, 0.12f, 0.15f, 0.16f};
	
	public GaussBlur() {
		super("gaussblur.vert", "gaussblurhori.frag");
	}

	@Override
	public void activate(){
		super.activate();
		GL20.glUniform1f(GL20.glGetUniformLocation(shader, "blurSize"), 1.0f / blurSize);
		
		for(int i = 0; i < layer.length; i++)
			GL20.glUniform1f(GL20.glGetUniformLocation(shader, "layer"+i), layer[i]);
	}
}

private long lastSystemTime = 0, frameChanger = 10, waiter = 0;
	private int changerate = 50;
	public boolean blurchanging;
	public void changeBlurFocus() {
	    waiter += System.currentTimeMillis() - lastSystemTime;
	    if(waiter >= frameChanger){
	        
	    	if(!focusblurScene){
	        	gaussblurParalax += changerate;
	        	gaussblurScene -= changerate;
	        	if(gaussblurParalax >= 512){
	        		gaussblurParalax = 512;
	        		blurchanging = false;
	        	}
	        	if(gaussblurScene <= 0) gaussblurScene = 0;
	        }
	        
	        if(focusblurScene){
	        	gaussblurScene += changerate;
	        	gaussblurParalax -= changerate;
	        	if(gaussblurScene >= 512){
	        		gaussblurScene = 512;
	        		blurchanging = false;
	        	}
	        	if(gaussblurParalax <= 0) gaussblurParalax = 0;
	        }
	    	
	        waiter -= frameChanger;
	    }
	    lastSystemTime = System.currentTimeMillis();
	}
```

Die in letzter Methode veränderte Zahl bezieht sich blurSize, bringt aber keine schönen Ergebnisse mit sich.

Leider weiß ich nicht genau, wie die Gewichtung "zur Mitte hin" und "zusammen 1 ergeben" gemeint ist, da meine Experimente meist dazu geführt haben, dass der Effekt zu einer Transparenz geführt hat oder die Unschärfe noch verstärkte.

Falls weitere Infos benötigt werden liefere ich diese gerne ^^


----------



## Guest2 (15. Dez 2011)

Also die blurSize sollte konstant bleiben und ist abhängig von der verwendeten Texturgröße. Was Du verändern müsstest, ist die Gewichtung. In dem Link ist die [c](0.05, 0.09, 0.12, 0.15, 0.16, 0.15, 0.12, 0.09, 0.05)[/c]. Z.B. sollte [c](0, 0, 0, 0.01, 0.98, 0.01, 0, 0, 0)[/c] schon relativ scharf sein. Der Wert in der Mitte entspricht dem Ursprungswert. Desto mehr von diesem Wert (und entsprechend weniger von den anderen) in die sum einfließt, desto schärfer wird das Bild. Die Summe sollte 1 ergeben, damit die Helligkeit unbeeinflusst bleibt.)

Alternativ könntest Du auch zwischen dem Originalfarbwert und dem sum blenden (ganz grob: 

```
color = texture2D(RTScene, vec2(vTexCoord.x, vTexCoord.y));
gl_FragColor = (variable * sum + (1 – variable) * color);
```
(das ist physikalisch allerdings noch "falscher" als blenden ohnehin schon ist ))

Viele Grüße,
Fancy


----------



## javaPanther (18. Dez 2011)

Hi danke dir für die Hilfestellung, das mit der 1 als Gesamtsumme hat auch meine Frage mit der variablen Helligkeit bereits vorweggenommen. Es funktioniert nun soweit einwandfrei. Für Alle die evtl eine Ähnliche Aufgabenstellung bearbeiten hier meine Gewichtungen für einen relativ flüssigen Übergang:


```
public float[][] layer = new float[][]{
			{1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
			{0.9f, 0.04f, 0.01f, 0.0f, 0.0f},
			{0.8f, 0.06f, 0.03f, 0.01f, 0.0f},
			{0.7f, 0.07f, 0.05f, 0.04f, 0.00f},
			{0.6f, 0.08f, 0.06f, 0.05f, 0.02f},
			{0.49f, 0.10f, 0.08f, 0.06f, 0.03f},
			{0.39f, 0.11f, 0.09f, 0.07f, 0.04f},
			{0.3f, 0.12f, 0.10f, 0.08f, 0.05f},
			{0.19f, 0.14f, 0.12f, 0.09f, 0.06f}
	};
```


----------

