检测后处理GLSL着色器上的灯光位置

时间:2015-05-30 18:53:28

标签: algorithm opengl graphics glsl shader

我正在尝试应用体积散射后处理,就像从Nvidia GPU Gems 3中提取的一样,现在我有这样的事情:

 float4 main(float2 texCoord : TEXCOORD0) : COLOR0  
{  
// Calculate vector from pixel to light source in screen space.  
half2 deltaTexCoord = (texCoord - ScreenLightPos.xy);  
// Divide by number of samples and scale by control factor.  
deltaTexCoord *= 1.0f / NUM_SAMPLES * Density;  
// Store initial sample.  
half3 color = tex2D(frameSampler, texCoord);  
// Set up illumination decay factor.  
half illuminationDecay = 1.0f;  
// Evaluate summation from Equation 3 NUM_SAMPLES iterations.  
for (int i = 0; i < NUM_SAMPLES; i++)  
{  
// Step sample location along ray.  
texCoord -= deltaTexCoord;  
// Retrieve sample at new location.  
half3 sample = tex2D(frameSampler, texCoord);  
// Apply sample attenuation scale/decay factors.  
sample *= illuminationDecay * Weight;  
// Accumulate combined color.  
color += sample;  
// Update exponential decay factor.  
illuminationDecay *= Decay;  
}  
// Output final color with a further scale control factor.  
return float4( color * Exposure, 1);  
}  

但是这个着色器需要光线均匀,我想是否可以使用后处理材料检测屏幕中光线的位置以及我如何做到这一点。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

单词&#39;检测&#39;听起来好像你正在尝试使用帧缓冲区中的信息来估计灯光的位置。没有好办法做到这一点。

相反,使用glUniform(在您的OpenGL应用程序中)将光的位置传递到着色器。您需要在着色器顶部附近声明您的灯光位置:

uniform vec2 ScreenLightPos;

如果灯光永不移动,您可以在着色器中将其位置设为常量:

const vec2 ScreenLightPos = vec2(0.5, 0.5);

或者,如果灯光可预测地移动,您可以根据时间计算它的位置:

vec2 ScreenLightPos = vec2(sin(time), cos(time));

基本上,在着色器运行之前,您需要知道灯光的位置。无论您是进行后处理还是表面照明,都是如此。

如果绝对没有其他方式,您可能可以使用compute shader或更糟糕的pixel reading来检测帧缓冲区上的明亮区域。这将是非常缓慢的,一旦你弄清楚你的光线在哪里,你仍然需要使用glUniform传递位置。如果即使这样也不是一个选项,你可以在着色器中使用嵌套循环在整个帧缓冲区中搜索亮点。我不打算解释如何做到这一点或为什么这是一个可怕的想法。