OGL Light Pre Pass

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Punika
Beiträge: 29
Registriert: 25.02.2002, 15:12
Echter Name: Lutz Hören
Kontaktdaten:

OGL Light Pre Pass

Beitrag von Punika »

Hi Zusammen,

ich arbeite gerade an einem Light Pre Pass Renderer. Gerade teste ich ihn mit einem simplen Directionalen Licht (also Fullscreen Quad).

Das ganze funktioniert auch wenn ich die Berechnung in Object-Space durchführe. Das heisst, Normale, Tangente, Bitangente werden im Vertex Shader einfach weitergegeben.
Die Licht Richtung übergebe ich auch in "Object Space".

Nun wollte ich die Berechnung aber gerne im View Space haben. Somit multipliziere ich die Normale, Tangente, Bitangente mit der gl_NormalMatrix (inverse transpose ModelView Matrix), das selbe mache ich ausserhalb meines Shader codes mit der Licht Richtung.

Und hier liegt das Problem. Es scheint als würden die Werte abhängig vom Winkel des Betrachtens sein. So als würde eine komponente also nicht im View Space sein.

Woran könnte das liegen?

Dieser shader erstellt mir die depth und normale

Code: Alles auswählen

// inputs
attribute vec4 position;
attribute vec4 texcoord0;
attribute vec4 normal;
attribute vec4 tangent;
attribute vec4 bitangent;

// outputs
varying float depth;
varying vec3 viewSpaceNormal;
varying vec3 viewSpaceTangent;
varying vec3 viewSpaceBitangent;
//varying mat3 tangentToView;

void main()
{
	// position in view space
	vec3 viewSpacePos = vec3( gl_ModelViewMatrix * position );
	
	// pass depth
	depth = viewSpacePos.z;

	// view space normal, tangent and bitangent
	viewSpaceNormal = normalize(gl_NormalMatrix * normal.xyz);
	viewSpaceTangent = normalize(gl_NormalMatrix * tangent.xyz);
	viewSpaceBitangent = normalize(gl_NormalMatrix * bitangent.xyz);

	// tangent space...
//	viewSpaceNormal = normal.xyz;
//	viewSpaceTangent = tangent.xyz;
//	viewSpaceBitangent = bitangent.xyz;

//	tangentToView = mat3( tangent, bitangent, normal );

	// set texture coordinates
	gl_TexCoord[0] = texcoord0;
	// transform into clip space
	gl_Position = gl_ModelViewProjectionMatrix * position;
}

// vertex Shader inputs
varying float depth;
varying vec3 viewSpaceNormal;
varying vec3 viewSpaceTangent;
varying vec3 viewSpaceBitangent;
//varying mat3 tangentToView;

// far clip plane
uniform float farClip;

// Compiler Textures
//@usertextures

// Compiler Constant Inputs
//@userconstants

// Compiler uniform Input
//œuservars

// material inputs
vec3 matNormalInput;

// Normal Map to View Space Normal
vec3 NormalMapToSpaceNormal(vec3 normalMap, vec3 normal, vec3 tangent, vec3 bitangent)
{
	normalMap = normalMap * 2.0 - 1.0;
	// fixme do we to transform it in range [0,1] (see above)
	normalMap = vec3(normal * normalMap.z + normalMap.x * tangent - normalMap.y * bitangent);
	return normalMap;
}

void main()
{
	//@matNormalInput

	// bring normal from [-1,1] to [0,1]
	vec3 n = NormalMapToSpaceNormal(matNormalInput, viewSpaceNormal, viewSpaceTangent, viewSpaceBitangent );
//	vec3 n = (matNormalInput * 2.0 - 1.0) * tangentToView;
	// Normals need to be adjusted from [-1, 1] to [0, 1]
	n = 0.5 * (normalize(n) + 1.0);
   
	vec2 encodeN = encodeNormal( n );

	// depth buffer
	gl_FragData[0] = packFloatTo4x8( -depth / farClip );
	// normal buffer
	gl_FragData[1] = pack2FloatTo4x8( encodeN );
}
Und hier der Shader für die Lichtberechnung

Code: Alles auswählen

// user inputs
uniform sampler2D depthTexture;
uniform sampler2D normalTexture;

//TODO
//uniform vec3 viewPosition;
//uniform vec3 viewDirection;

// light dir in view space
uniform vec3 lightDir;

// vertex shader inputs
varying vec3 frustumRay;

void main()
{
	const vec3 lightColor = vec3( 0.7, 0.7, 0.7 );
	const float specularPower = 16.0;

	// get dpeth
	float depth = unpack4x8ToFloat( texture2D(depthTexture, gl_TexCoord[0].xy) );
	// Reconstruct position from the depth value, making use of the ray pointing towards the far clip plane
	vec3 pos = frustumRay * depth;

	// decode and unpack normal
	vec3 normal = decodeNormal( vec4( unpack4x8To2Float( texture2D(normalTexture, gl_TexCoord[0].xy) ), 0.0, 0.0 ) );
	//FIXME Convert normal back from [0,1] to [-1,1]
	normal = (normal * 2.0) - 1.0;
	
    
	// N dot L lighting term
	float nl = clamp( dot(normal, -lightDir), 0.0, 1.0 );

	// lighting
	gl_FragColor = vec4( lightColor * nl, 1.0 );
	// depth
//	gl_FragColor = vec4( depth, depth, depth, 1.0 );
	// normal
//	gl_FragColor = vec4( normal.x, normal.y, normal.z, 1.0 );
}

// stream inputs
attribute vec4 position;
attribute vec4 texcoord0;

// outputs
varying vec3 frustumRay;

// user inputs
uniform vec2 lightbufferSize;
uniform vec3 frustumCorners[4];
	
// get the right frustum ray
vec3 GetFrustumRay( vec2 texCoord )
{
	int index = int(texCoord.x + (texCoord.y * 2.0));
	return frustumCorners[index];
}

void main()
{
	gl_TexCoord[0] = texcoord0;
	frustumRay = GetFrustumRay( texcoord0.xy );
        // add half pixel
	gl_TexCoord[0].xy += lightbufferSize;

	gl_Position = vec4(position.xy, 0.0, 1.0 );
}
Vielen Dank fürs darüber schauen...
Punika
Beiträge: 29
Registriert: 25.02.2002, 15:12
Echter Name: Lutz Hören
Kontaktdaten:

Re: OGL Light Pre Pass

Beitrag von Punika »

Hallo nochmal

hat wirklich niemand eine Idee? Hab das nochmal auf ein Minimum konstruiert. Benutze keine World Matrix. Nehme im Moment nur die Normale der Geometry, keine Normal Map.

Das ganze funktioniert nur im Object Space. So bald ich die View Matrix mit einbeziehe und die Kamera rotiere gehen meine Normalen nicht hand in hand. Wobei ich z.B. schon versucht habe einfach auch meinen Licht richtungsvektor mit der normalen Matrix zu transformieren. Immer das gleiche Ergebnis.

Danke

Punika
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: OGL Light Pre Pass

Beitrag von dot »

Und es liegt sicher an den Normalen? Also gibst du dir die Normalen aus und siehst dass sie falsch sind? Oder ist nur das Ergebnis ein anderes als das von dir erwartete!?
Antworten