Blending multiple lights in deferred renderer

Started by
9 comments, last by kalle_h 11 years, 8 months ago
http://code.google.c...20prelightpass/
Very simple reference implementation of prelight pass renderer for gles2.0

Renderer batch points lights up to 50 per draw call. One point light is just very crude sphere mesh where each vertex have index for light position, range and color.
With openGL you can do proper instancing but with gles2.0 you have to be creative.
Rendering flow is something like that.

1. Draw minimal g-buffer.
2. Draw visible lights to separate fbo. Upload light data as uniform arrays. 60 per batch.
3. Draw geometry second time.

[source lang="cpp"]#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif

attribute vec4 a_position;

uniform mat4 u_projectionMatrix;
uniform vec4 lightPos[60];
uniform vec4 lightColor[60];

varying vec3 v_lightColor;
varying vec4 v_lightPos;

varying vec4 v_texCoords;
varying vec3 v_viewRay;
void main()
{
int i = int(a_position.w);
v_lightColor = lightColor.rgb;
vec4 data = lightPos;
v_lightPos = data;
vec4 pos = vec4((data.xyz + a_position.xyz / data.w), 1.0);
v_viewRay = pos.xyz;
v_texCoords = u_projectionMatrix * pos;
gl_Position = v_texCoords;
v_texCoords.xy += v_texCoords.w;
v_texCoords.xy *=0.5;
}

[/source]

[source lang="cpp"]#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif

uniform sampler2D u_texture0;

uniform float far; // 1/far
varying vec4 v_lightPos;
varying vec3 v_lightColor;

varying vec4 v_texCoords;
varying vec3 v_viewRay;


const float shininessFactor = 25.0;

const vec2 bitShifts = vec2(1.0 / 256.0, 1.0);
float unPack(vec2 zz)
{
zz *= bitShifts;
return (zz.x + zz.y);
}

void main()
{
vec4 texture = texture2DProj(u_texture0,v_texCoords);
float depth = -unPack(texture.rg);

vec2 fenc = texture.ba * 4.0 - 2.0;
float f = dot(fenc,fenc);
vec3 surfaceNormal = (vec3(fenc * sqrt(1.0 - f * 0.25), 1.0 - f * 0.5));



vec3 viewRay = vec3(v_viewRay.xy * (far / v_viewRay.z), far);
vec3 vPos = viewRay * depth;
vec3 fromEye = -normalize(vPos);

vec3 lightDiffer = v_lightPos.xyz - vPos;
float lightDis = length(lightDiffer);
vec3 lightDir = normalize(lightDiffer);

float diffuse = dot(surfaceNormal, lightDir ) + 1.0;

//blinn
vec3 halfAngle = normalize(lightDir + fromEye);
float specular = pow(clamp(dot(halfAngle, surfaceNormal),0.0,1.0), shininessFactor);

specular *= diffuse ;

float intensity = diffuse * max(1.0 - lightDis * v_lightPos.w,0.0);

gl_FragColor = clamp(intensity * vec4(v_lightColor, specular*0.5),0.0,1.0);
}[/source]

This topic is closed to new replies.

Advertisement