• Добро пожаловать на Quest3D - Русскоязычное сообщество.
 

"Крутизна и реализьм" - тема про шейдеры

Автор KBECT0MAH, 25 декабря 2007, 04:18:22

« назад - далее »

Sqwer

чем и как мерил? надеюсь  по мс и при статической камере в релиз режиме при одинаковой загрузке проца.

если это  простая логика (умножить/разделить/добавить)
то  на глаз ничего не поменяется, даже если это цикл


а вот такие тяжёлые операции как (чтение текстурного семплера / возведение в степень) - существенно влияют на скорость
(на это следует обратить особое внимание , если захочень создать рельефную имплементацию )


вполне возможно копилятор HLSL эффектов Квеста не устанавливает необходимые флаги оптимизации, игнорируя атрибуты.


В нашем с Русланом двиге на ДХ10 ввод  условных операторов на чтение текстур давал большой прирост. (конечно у нас и текстурки не "детские" : 3 чётырёх HDR(16 float) канальные текстуры ), логика была простой, по глубине проверяли стоит ли  читать G буфер. Если небо - то  пропускаем / если объекты - то читаем.

Cludz

#136
поковырялся в коде Sqwer*а к сожалению он не дает нужного мне результата
картинка сделана в максе но суть думаю понятна
http://piccy.info/view3/1037622/e2f195900a9508a20794e075cfe5457a/
Skype "Cludz159"

Sqwer

#137
2Cludz
Цитироватьпоковырялся в коде Sqwer*а к сожалению он не дает нужного мне результата

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


но в любом случае  тебе надо использовать эмбиент свет

найди кусок кода


Цитироватьfloat3 sumLight=0;

   sumLight+=float3(0.2f,0.2f,0.2f);

   sumLight+=lightcol[0]*CalculateLightInfluance(N,IN.LightVector0,light_atten[0]);
   sumLight+=lightcol[1]*CalculateLightInfluance(N,IN.LightVector1,light_atten[1]);

вставь   то , что отмечено красным
это и есть эмбиент цвет

dfx

Цитироватьчем и как мерил? надеюсь  по мс и при статической камере в релиз режиме при одинаковой загрузке проца.

Нет. Мерил на глаз. Блок достаточно тяжелый, что бы не заметить разницы. В блоке я делаю размытие по гаусу 3х6 + шум. Т.е. 18 выборок в цикле из одной текстуры + столько же выборок из текстуры шума. коэффициент размытия зависит от значения читаемого из текстуры. При значения близким к 0 этот фильтр должен отключаться, а так же в зависимости от значения коэффициента хотелось бы снижать количество интераций.
Получается, что если на входе все пиксели текстуры =0, то производительность такая же, как если бы текстура имела бы значение >0, т.е. низкая. Можно попробовать прерывать цикл. 

Цитироватьвполне возможно копилятор HLSL эффектов Квеста не устанавливает необходимые флаги оптимизации, игнорируя атрибуты.
Это так, компилятор квеста не понимает такие флаги. По крайней мере "в лоб" не прокатило.

Sqwer

ЦитироватьЭто так, компилятор квеста не понимает такие флаги. По крайней мере "в лоб" не прокатило.
печально, надо протестить

если инфа подтвердится, то   единственный выход -  создать свой рендер.

Cludz

Alteste выложи пожалуйста свой код для 2х ИС
если можно с описанием  ::)
http://upload.com.ua/get/902316716/We die standing.cgr
Мои дебри только тссс :D
Skype "Cludz159"

dfx

#141
Cludz, а чего сам не добавишь второй источник? Ты же уже посчитал направление для него?
Скопируй код для первого источника, но подставь вектор другого. Типа того - 
// Пиксельный шейдер
float4 PS(v2f IN) : COLOR
{
float3 N = normalize(IN.wnormal);

//Считаем для первого ИС
float3 L1 = normalize(IN.LightVector0);
float diffuseL1 = dot(N,L1);
float attenL1 = saturate(1.0 - dot(IN.LightVector0, IN.LightVector0)); // Затухание для первого ИС
float3 lColorL1 = lightcol[0]*diffuseL1*attenL1;

//Считаем для второго ИС
float3 L2 = normalize(IN.LightVector1);
float diffuseL2 = dot(N,L2);
float attenL2 = saturate(1.0 - dot(IN.LightVector1, IN.LightVector1)); // Затухание для второго ИС
float3 lColorL2 = lightcol[1]*diffuseL2*attenL2;


    float4 tex = tex2D(Texture1, IN.texCoor.xy);


float3 result = (lColorL1+lColorL2)*DiffuseColor*tex;
return float4(result,1);
}


Но, все равно, логичнее выносить идентичные блоки вычислений в функции, как у Sqwer'а

А в коде у Alteste, выложенном тобой, тоже считаются 2 ИС, но там ошибка:
float atten = saturate(1.0 - dot(IN.LightVector0, IN.LightVector0)); // Затухание
    float4 tex = tex2D(Texture1, IN.texCoor.xy);
float3 resultA = lightcol[0]*diffuse*DiffuseColor*atten*tex;
float3 resultB = lightcol[1]*diffuse1*DiffuseColor*atten*tex;

Обрати внимание, что для затухания второго источника используются данные первого.

Кстати да, какой смысл в выражении "saturate(1.0 - dot(IN.LightVector0, IN.LightVector0));" так и не понял) Т.к. результат = 0 при любом раскладе. Затухание не так считается, эт точно.)

Cludz

#142
для меня код как незнакомые английские слова))
то я пробовал продублировать, до ума так и не довел
в шейдерах копаюсь 3й день
спасибо за разъяснения
Skype "Cludz159"

Sqwer

2 dfx

ЦитироватьНет. Мерил на глаз. Блок достаточно тяжелый, что бы не заметить разницы.
только что проверил работу  ветвления IF - раздница есть


проверял так:

Цитироватьif (yes>1)
  {
  for( int i = 0;i < 100; i++ )
    {

   aldedo       += tex2D (gAlbedoMap, pIn.texC );
   normal       += tex2D (gNORMALMap, pIn.texC );
   position    += tex2D (gPOSITIONMap, pIn.texC );
   self      += tex2D (gSELFILLUMMap, pIn.texC );
   
     }

   }

каждая текстура -  4 каналка на 16float каждый

в цикле проганяется чтение  из 4ех текстур   100 раз

переменную  по которой происходит условие  "yes"   брал с внешней переменной, прилинкованной к HLSL каналу.


при yes=0    FPS  = 200
при yes=20   FPS  = 50

так что бранчинг влияет

=======================================================

ЦитироватьЭто так, компилятор квеста не понимает такие флаги. По крайней мере "в лоб" не прокатило.

так точно!

проверил:
перед   if (yes>1)    поставил   [branch]
  [branch] if (yes>1) 

квестовый анализатор семантики  выдал ошибку
unexpected token [
,  хотя в реальности ошибки нет  :P

но хорошо, что по умолчанию  стоит атрибут branch








Alteste

Цитата: Sqwer от 31 января 2011, 16:17:39
Ниже рабочий пример    "как это делается" +  вывел расчёт  параметров ИС  в  методы, что  сократит инструкции  8)
Сквер, ты из параметра затухание (аттенюэйшн) сделал силу света:
I = cos(L,N)* LightPower - получился обычный директник
Смысл в том, чтобы свет затухал на расстоянии.
Именно затухание отличает пойнтлайт от директа, посмотри мой пример еще раз https://guest3d.wohlnet.ru/forum/index.php?topic=1688.0

Sqwer

ЦитироватьИменно затухание отличает пойнтлайт от директа


отличает поинт от директа    вектор освещения!!
а не только аутенация

Для поинта он расчитывается: как нормализация раздницы(  позиция источника света - позиция поверхности)
учитывается затухание по расстоянию


Для директа он расчитывается: как нормализация раздницы (позиция источника света - 0)
затухание по расстоянию не учитывается



ЦитироватьI = cos(L,N)* LightPower - получился обычный директник
мдя  оппечатался
вот поправленный вариант

Alteste


dfx

#147
Цитироватьпеременную  по которой происходит условие  "yes"   брал с внешней переменной, прилинкованной к HLSL каналу.
В этом то и проблема. Я переменную для некоторых условий читаю из текстуры. Если читать из вне, то работает.
Вот кусочек кода для примера:
float3 refColor;
float glossiness = useGlossinesTexture==1?tex2D(glossinessSampler,In.texCoord.xy).r:iGlossiness;
float anisotropy = useAnisotropyTexture==1?tex2D(anisoSampler,In.texCoord.xy).r:iAnisotropy;
float anisoDir = useAnisoDirTexture==1?tex2D(anisoDirSampler,In.texCoord.xy).r:iAnisoDir;
float metallness = useMetallnessTexture==1?tex2D(metallnessSampler,In.texCoord.xy).r:iMetallness;

if (glossines == 0)
{
    float3 refVec = -reflect(eyeVec,Nn);
    refColor = texCUBE(envSampler,refVec);

}
else
{
    refColor = cubeBlur(envSampler,Nn,Bn,Tn,glossiness,Anisotropy,anisoDir,eyeDir);

}
if (metallness<1)
{
    refColor *= fresnel(eyeVec,Nn,frIOR);
}


Если использовать значения из вне, типа этого:

float3 difColor=0;
if (difCalcType==useDifCubeTexture)
{
    difColor +=texCUBE(difCubeSampler,Nn);
}
if (difCalcType==useEnvCube_Linear)
{
    difColor += createDifLightLinear(envCubeSampler,Nn);
}
if (difCalcType==useEnvCube_Cubic)
{
    difColor += createDifLightCubic(envCubeSampler,Nn);
}


вроде работает.

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

Sqwer

ЦитироватьИли тут имеется ввиду, что должно компилироваться, если бы не квестовый анализатор?
ага

dfx

#149
Да уж. В квесте море таких моментов(
Кстати,
Цитироватьпроверял так:


Цитировать
if (yes>1)
  {
  for( int i = 0;i < 100; i++ )
    {

   aldedo       += tex2D (gAlbedoMap, pIn.texC );
    normal       += tex2D (gNORMALMap, pIn.texC );
   position    += tex2D (gPOSITIONMap, pIn.texC );
   self      += tex2D (gSELFILLUMMap, pIn.texC );
   
     }

   }

каждая текстура -  4 каналка на 16float каждый

в цикле проганяется чтение  из 4ех текстур   100 раз

это не совсем медленно) При выборке одного пикселя из текстуры по одним и тем же координатам не сильно просадит фпс, т.к. эти данные кэшируются и после первой выборки чтение идет из кеша. А значит эта тяжелая инструкция используется один раз. Т.е. образно -
aldedo       += tex2D (gAlbedoMap, pIn.texC );
normal       += tex2D (gNORMALMap, pIn.texC );
position    += tex2D (gPOSITIONMap, pIn.texC );
self      += tex2D (gSELFILLUMMap, pIn.texC );

for( int i = 0;i < 100; i++ )
    {
aldedo       += aldedo;
normal       += normal;
position    += position;
self        +=self;
    }



Кроме того компилятор может просечь что к чему и на выходе сделать вообще так:
aldedo       += tex2D (gAlbedoMap, pIn.texC )*100;
normal       += tex2D (gNORMALMap, pIn.texC )*100;
position    += tex2D (gPOSITIONMap, pIn.texC )*100;
self      += tex2D (gSELFILLUMMap, pIn.texC )*100;

Что, конечно не факт.

Но если каждую интерацию читать пиксель по случайным координатам и использовать большой разброс, то 50 фпс точно не будет)