Перейти к контенту

Рекомендуемые сообщения

Anonim   

Привет всем, недавно задался вопросом реализации бликов like battlefield, наткнулся на статью:

 

John Chapman Pseudo Lens Flares

 

Демонстрационное видео мне понравилось, посему взялся за реализацию прямо по статье. Вот что вышло у меня: клик

Собтсвенно, а как оно делается на сталкере, весь код приведу ниже с пояснением.

 

Шейдер Treshold/Downsample, так как реализация в статье не подходит для сталкера, пришлось делать совсем иначе, на выходе почти идентичный результат. А что он делает? Говоря "поруски", отбрасывает пиксели с низкой яркостью оставляя только светлые участки, т.е. те участки которые и будут учавствовать в создании призраков и гало эффекта. Шейдер можно сказать необходимый, его можно использовать и для эффекта Dirty Lens, похожим способом и блум пилится и ещё много чего. Из входных данных, это люминанс вектор и rt_Generic_0(сцена до фазы combine). 

 

Пишется всё это дело в новый рендер таргет, который мы дальше будем использовать для генерирования бликов.

Скрытый текст

#include "common.h"

uniform	sampler2D	samplerScene;//rt_Generic_0
uniform	half4	uLuminance;//luminance vector
//////////////////////////////////////////////////////////////////////////////////////////
//
half4		main		(	AntiAliasingStruct	INStruct	)		:		COLOR
{
	half3	color	=tex2D(samplerScene,INStruct.texCoord0.xy).rgb;
	half3	brightColor	=max(color	-uLuminance.xyz,	0);
	half	bright	=dot(brightColor,	1);
	bright	=smoothstep(0,	.5,	bright);
	half3	outColor	=lerp(0,	color,	bright);
	return	half4	(outColor,	1);
}

 

 

Терь сам шейдер генерирующий блики. Входные данные:

-ранее созданный рендер таргет downsample, "обозванный" samplerTreshold

-1D текстура, в нашем случае фейковая, т.к. нельзя в dds сохранить текстуру с высотой в один пиксель, у меня она 256x4. Используется она для окрашивания бликов.

Всё это тоже пишется в новый РТшник.

Скрытый текст

#include "common.h"

half3	tex2Ddistorted(sampler2D inputSampler, float2 texCoord, float2 direction, float3 distortion)
{
	return	half3
	(
	tex2D(inputSampler,	texCoord	+direction	*distortion.r).r,
	tex2D(inputSampler,	texCoord	+direction	*distortion.g).g,
	tex2D(inputSampler,	texCoord	+direction	*distortion.b).b
	);
}

#define	GHOSTS	int(5)//num of ghosts

uniform	sampler2D	samplerTreshold;//treshold sampler
uniform	sampler2D	samplerLensColor;//fake1D texture
uniform	half4	uGhostDispersal;
uniform	half4	uHaloWidth;
uniform	half4	uDistortion;
//////////////////////////////////////////////////////////////////////////////////////////
//
half4		main		(	AntiAliasingStruct	INStruct	)		:		COLOR
{
	float2	texCoord	=-INStruct.texCoord0.xy	+float2(1,1);
	float3	distortion	=float3(-screen_res.z	*uDistortion.x,	0,	screen_res.z	*uDistortion.x);
	
	float2	ghostVector	=(float2(.5,.5)	-texCoord)	*uGhostDispersal.x;
	float2	direction	=normalize(ghostVector);
	
	half3 outColor=half3(0,0,0);
//	half4 outColor=half4(0,0,0,0);
	for	(	int i=0;	i<GHOSTS;	i++	)
	{
		float2 offset	=frac(texCoord	+ghostVector	*float(i));
		
		float weight	=length(float2(.5,.5)	-offset)/length(float2(.5,.5));
		weight	=pow(1-weight,10);
		
		//outColor	+=tex2D(samplerTreshold,offset)	*weight;//.rgb	*weight;
		outColor	+=tex2Ddistorted(samplerTreshold,offset,direction,distortion).rgb	*weight;
	}
	
	//outColor*=tex2D(samplerLensColor,length(float2(.5,.5)	-texCoord)/length(float2(.5,.5)));//.rgb;
	outColor*=tex2Ddistorted(samplerLensColor,length(float2(.5,.5)	-texCoord)/length(float2(.5,.5)),direction,distortion).rgb;
	
	float2	haloVector	=normalize(ghostVector)	*uHaloWidth.x;
	float	haloWeight	=length(float2(.5,.5)	-frac(texCoord	+haloVector))/length(float2(.5,.5));
	haloWeight	=pow(1-haloWeight,5);
	//outColor	+=tex2D(samplerTreshold,texCoord	+haloVector)	*haloWeight;//.rgb	*haloWeight;
	outColor	+=tex2Ddistorted(samplerTreshold,texCoord	+haloVector,direction,distortion).rgb	*haloWeight;
	
	return	half4(outColor,	1);
	//return outColor;
}

 

 

Терь нужно "пустить под блюр" сгенерированные блики, обычно я это делаю незамысловатым Gauss блюром, но в сей раз хотел испробовать что-нибудь новенькое. На самом деле я не ручаюсь за правильность работы этого шейдера :biggrin:, так как не выводил его на результ для проверки. Чтобы перестраховаться можно использовать проверенный блюр, код будет прямо под этим.

Скрытый текст

#include "common.h"
uniform    sampler2D    samplerBlur;
//////////////////////////////////////////////////////////////////////////////////////////
//
half4        main        (    AntiAliasingStruct    INStruct    )        :        COLOR
{
    float    offset[3]    =
    {
        0,
        1.3846153846,
        3.2307692308
    };
    float    weight[3]    =
    {
        0.2270270270,
        0.3162162162,
        0.0702702703
    };    
    
    half4    outColor    =tex2D(samplerBlur,(INStruct.texCoord0.xy))    *weight[0];///1024    );
    
//    float    offset[3]    =
//    {
//        0,
//        1.3846153846,
//        3.2307692308
//    };
//    float    weight[3]    =
//    {
//        0.2270270270,
//        0.3162162162,
//        0.0702702703
//    };
    
    //for    (    int i=0;    i<2;    i++)
    for    (    int i=1;    i<3;    i++)
    {
        outColor    +=tex2D(samplerBlur,(INStruct.texCoord0.xy    +float2(0,offset)    ))*weight;///1024    )    *weight;
        outColor    +=tex2D(samplerBlur,(INStruct.texCoord0.xy    -float2(0,offset)    ))*weight;///1024    )    *weight;
    }
    
    return outColor;
}

 

 

Тут Gauss.

Входные параметры:

-семплер обречённый на блюр

-текстурные координаты

-сила блюра (почему в int? потомучто я всегда его использую только в цикле и как сила блюра у меня выступает кол-во оборотов цикла, к тому же значение динамическое)

 

for	(	int	i=0;	i<BLUR_SAMPLES;	i++	)
{
  outColor	=Gauss(samplerBlur,texCoord,i,false);
}

 

-бул значение для юза оптимизированного блюра

 

Примечание: по сути, юниформ screen_res здесь не так важен и можно заменить универсальной константой 1024.f:big_boss:

 

Скрытый текст

#ifndef GAUSSBLUR_H_INCLUDED
#define GAUSSBLUR_H_INCLUDED

half4 Gauss(sampler2D inputSampler, float2 texCoord, int factor, bool optimize)
{
	half4 outColor;
	
	if(!optimize)
	{


		float dx = factor*.5f/screen_res.x;
		float dy = factor*.5f/screen_res.y;
		
		outColor =
		(
		//1.f * tex2Dlod(inputSampler,float4(texCoord,0,0)).rgba +
		1.f * tex2Dlod(inputSampler,float4(texCoord+float2(dx,0),0,0)).rgba +
		1.f * tex2Dlod(inputSampler,float4(texCoord+float2(dy,0),0,0)).rgba +
		1.f * tex2Dlod(inputSampler,float4(texCoord+float2(-dx,0),0,0)).rgba +
		1.f * tex2Dlod(inputSampler,float4(texCoord+float2(-dx,-dy),0,0)).rgba +
		1.f * tex2Dlod(inputSampler,float4(texCoord+float2(dx,-dy),0,0)).rgba
		)/5.f;
	}
	else
	{

		const float delta = factor * (.5f/screen_res.x);
		
		outColor =
		(
		tex2Dlod(inputSampler,float4(texCoord+delta,0,0)).rgba +
		tex2Dlod(inputSampler,float4(texCoord-delta,0,0)).rgba
		)*(1.f/2.f);
	}
	
	return outColor;
}

#endif//GAUSSBLUR_H_INCLUDED

 

 

 

В идеале, конечно, я бы и Dawnsample обрёк на блюр, но переделывать было уже лень.:biggrin:

 

Ну и последняя фаза комбайн с основным изображением. Не стал парится с SturBurst эффектом, оставил статичным, оно и так прилично выглядит, DirtyLens Тоже не стал делать, так как у меня это отдельная история, хотя смешивать его тоже в этом шейдере буду.

Скрытый текст

#include "common.h"

uniform	sampler2D	samplerFlares;//lens flares sampler
//uniform	sampler2D	samplerDirt;//dirty texture
uniform	sampler2D	samplerScene;//rt_Generic_0
uniform	sampler2D	samplerStarbust;//
//////////////////////////////////////////////////////////////////////////////////////////
//
half4		main		(	AntiAliasingStruct	INStruct	)		:		COLOR
{
//	half4 lensDirt	=tex2D(samplerDirt,INStruct.texCoord0.xy);
//	half4 lensMod	=tex2D(samplerFlares,INStruct.texCoord0.xy)	*lensDirt;
	half4 starbust	=tex2D(samplerStarbust,INStruct.texCoord0.xy);
	half4 lensMod	=tex2D(samplerFlares,INStruct.texCoord0.xy)	*starbust;
	half4 scene	=tex2D(samplerScene,INStruct.texCoord0.xy)	+lensMod;
	return	scene;
}

 

 

Ну вроде всё. Надеюсь кому-нибудь пригодится.

Изменено пользователем Anonim

  • http://www.amk-team.ru/forum/uploads//ratings/bf.gif × 1
  • http://www.amk-team.ru/forum/uploads//ratings/wrench_orange.png × 3

Поделиться этим сообщением


Ссылка на сообщение
Поделиться на других сайтах

  • Недавно просматривали   0 пользователей

    Ни один зарегистрированный пользователь не просматривает эту страницу.

×