Анимация природных явлений
От: VVV Россия  
Дата: 27.12.17 00:27
Оценка:
Огонь, вода, туман, облака, песок и т.д. Хочется найти что-то почитать по _программной_ анимации этих процессов.
К сожалению, поиск ведёт на фотошоп и создание _покадровой_ анимации (и то не всего, чего хочется.. обычно "огнём" ограничивается).
Вопросы к игроделам: используется ли программная анимация в играх? или только покадровая, нарисованная художниками заранее?
Есть ли ресурсы в сети (и какие) откуда стоит начать поизучать этот вопрос?

Есть что-то вроде задумки — жмёшь мышью и в это место бьёт молния.. Как такое реализовать? если хочется, чтобы молния шла с разных сторон — мышь слева, молния справа, мышь слева сверху, молния справа снизу и т.д.. заранее нарисованными все положения просто быть не могут.. т.е., скорее всего, нужен программный рендеринг? Или есть хитрые техники?
Re: Анимация природных явлений
От: CEMb  
Дата: 01.01.18 17:23
Оценка: 6 (1)
Здравствуйте, VVV, Вы писали:

VVV>Вопросы к игроделам: используется ли программная анимация в играх? или только покадровая, нарисованная художниками заранее?

Не совсем про игры, но я делал программно так (там ещё есть вода и северное сияние)
Пререндерено там 10-15 кадров для одного сполоха в чёрно-белом варианте. Потом на него накладывается сверху градиент, уже не помню, или по цвету или по прозрачности. Сполохи спаунятся рандомно по X и движутся вверх по Y, смешиваясь между собой или по прозрачности или через фильтр (screen из фотошопа). Бонус такой реализации в том, что можно использовать разные градиенты, можно использовать разные спрайты, можно мешать разными фильтрами, можно использовать разные алгоритмы передвижения, у меня, например, там заметно, что иногда сполохи сбиваются в кучу, в реальности это происходит над особо горячими точками, где горячий воздух поднимается вверх, вызывая притоки воздуха со сторон, которые наклоняют к центу боковые сполохи, образуя такую огненную горку.
VVV>Есть ли ресурсы в сети (и какие) откуда стоит начать поизучать этот вопрос?
Я просто сидел рассматривал огонь в slowmo, думал, как это можно реализовать в цифре. Пробовал разные варианты. Надо было, наверно, написать статейку на эту тему

VVV>Есть что-то вроде задумки — жмёшь мышью и в это место бьёт молния.. Как такое реализовать? если хочется, чтобы молния шла с разных сторон — мышь слева, молния справа, мышь слева сверху, молния справа снизу и т.д.. заранее нарисованными все положения просто быть не могут.. т.е., скорее всего, нужен программный рендеринг? Или есть хитрые техники?

алгоритм построения реалистичной молнии где-то есть, я на что-то такое натыкался. Там что-то похожее на фракталы. Сначала ты рисуешь прямую. Потом делишь пополам, середину рандомно отводишь в сторону. Потом каждый отрезок делишь пополам, середины отводишь рандомно в сторону. Несколько раз повторяешь, получается подобие молнии.
Re: Анимация природных явлений
От: Adnin  
Дата: 02.01.18 15:14
Оценка: 6 (1)
Здравствуйте, VVV, Вы писали:

VVV>Огонь, вода, туман, облака, песок и т.д. Хочется найти что-то почитать по _программной_ анимации этих процессов.

VVV>К сожалению, поиск ведёт на фотошоп и создание _покадровой_ анимации (и то не всего, чего хочется.. обычно "огнём" ограничивается).
VVV>Вопросы к игроделам: используется ли программная анимация в играх? или только покадровая, нарисованная художниками заранее?

Используется. Используют например фрактальі, шум Перлина,...
Гуглить например так:
procedural water/clouds/flame/terrain generation/simulation in games

VVV>Есть ли ресурсы в сети (и какие) откуда стоит начать поизучать этот вопрос?


С чего начать не знаю, но вот тебе ссьілки для затравки:
http://vterrain.org/Atmosphere/rain.html
http://vterrain.org/Atmosphere/Clouds/index.html
http://www.uraldev.ru/articles/35
http://www.uraldev.ru/articles/29
https://habrahabr.ru/post/249027/
http://www.davideaversa.it/wp-content/uploads/2015/06/Procedural-Contents-Generation.pdf
Отредактировано 02.01.2018 15:17 Adnin . Предыдущая версия .
Re: Анимация природных явлений
От: velkin Удмуртия http://blogs.rsdn.org/effective/
Дата: 02.01.18 16:22
Оценка: 1 (1) -1 :)
Здравствуйте, VVV, Вы писали:

VVV>Есть ли ресурсы в сети (и какие) откуда стоит начать поизучать этот вопрос?


Можно купить Garrys_Mod, сейчас он по скидке -50% 249 pуб. = 124,50 pуб., хотя даже и без этого ничего не стоит по сравнению с другими играми. Дальше заходишь в мастерскую Steam по Garry's Mod или предварительно на ютуб, а потом всё равно в мастерскую и выбираешь понравившийся мод. Можно добавлять моды прямо из игры.

VVV>Есть что-то вроде задумки — жмёшь мышью и в это место бьёт молния.. Как такое реализовать?


Этот мод скорее всего будет относиться к классу оружия, но лучше фильтровать по Addon. Чисто для примера ищу мод и первый попавшийся:

https://steamcommunity.com/sharedfiles/filedetails/?id=268330169

Захожу в игру и испытываю, после выбора оружия шторма левой стрелять, правой менять эффекты. Графика в этом моде не самая лучшая, есть выглядящие более чем современно, а есть вот такие, но не суть. Предположим мне понравилось или просто захотелось посмотреть, что внутри. Распаковка программой gmad.exe, нужно навести на файл storm_swep_268330169.gma и "открыть с помощью" выбрав эту программу. Она находится в "...\Steam\steamapps\common\GarrysMod\bin".

...\Steam\steamapps\common\GarrysMod\garrysmod\addons\storm_swep_268330169

А там иконка оружия, это файлы weapon_stormswep.vmt и weapon_stormswep.vmf, последний является изображением.
  weapon_stormswep.vmt
"UnlitGeneric" 
{ 
    "$basetexture"        "vgui/entities/weapon_StormSwep" 
    "$vertexcolor"         1 
    "$vertexalpha"         1 
    "$nolod"             1 
}

И код:
  cl_init.lua
include('shared.lua')

SWEP.PrintName            = "StormSwep"            
SWEP.Slot                = 3
SWEP.SlotPos            = 1
SWEP.DrawAmmo            = false
SWEP.DrawCrosshair        = true

  init.lua
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include('shared.lua')


SWEP.Weight                = 1
SWEP.AutoSwitchTo        = true
SWEP.AutoSwitchFrom        = false

  shared.lua
SWEP.Author            = "Sylar"
SWEP.Contact        = "Sylar @ facepunch"
SWEP.Purpose        = ""
SWEP.Instructions    = "Attack1: FireStorm \n Attack2: Lightning Storm\n Attack2 + use : Lightning @ target"

SWEP.Spawnable            = true
SWEP.AdminSpawnable        = true

SWEP.ViewModel            = "models/weapons/v_smg1.mdl"
SWEP.WorldModel            = "models/weapons/w_smg1.mdl"

SWEP.Primary.ClipSize        = -1
SWEP.Primary.DefaultClip    = -1
SWEP.Primary.Automatic        = false
SWEP.Primary.Ammo            = "none"

SWEP.Secondary.ClipSize        = -1
SWEP.Secondary.DefaultClip    = -1
SWEP.Secondary.Automatic    = false
SWEP.Secondary.Ammo            = "none"
AddCSLuaFile( "shared.lua" )

local Prim = Sound( "ambient/explosions/explode_2.wav" )
local Pew = Sound ( "ambient/explosions/exp4.wav" )
local Wam = Sound( "ambient/atmosphere/thunder4.wav")

function SWEP:Reload()
end


function SWEP:Think()
end

ShotMode = 1

function SWEP:PrimaryAttack()
if (!SERVER) then return end
tr = self.Owner:GetEyeTrace()
    hitpos = tr.HitPos


    self.Weapon:SetNextPrimaryFire( CurTime() + 5 )

    self.BaseClass.ShootEffects( self )

if (ShotMode == 1) then
self.Weapon:EmitSound("ambient/atmosphere/thunder4.wav")
self.Weapon:EmitSound("ambient/explosions/exp4.wav")
self.Weapon:EmitSound("ambient/explosions/explode_2.wav")

        timer.Simple(0,FSS)

        
    end

if (ShotMode == 4) then
    timer.Simple(0,FFR)
    timer.Simple(0,FFRG)
end

if (ShotMode == 2) then
self.Weapon:EmitSound("ambient/atmosphere/thunder4.wav")
self.Weapon:EmitSound("ambient/explosions/exp4.wav")
self.Weapon:EmitSound("ambient/explosions/explode_2.wav")

    timer.Simple(0,LSS)
        if ( !self.Owner:KeyDown( IN_USE )== false ) then
                timer.Simple(0,LSSa)
            end
        if ( !self.Owner:KeyDown( IN_USE )== true ) then 
                timer.Simple(0,LSSb)
            end

    end

if (ShotMode == 3) then
        timer.Simple(0,SSS)
        
    end
end


    

function SWEP:SecondaryAttack()
tr = self.Owner:GetEyeTrace()
    hitpos = tr.HitPos

self.Weapon:SetNextSecondaryFire( CurTime() + 1 )
if (ShotMode == 1) then
text1 = "Storm Choice : Fire Tornado"
  self.Owner:PrintMessage( HUD_PRINTCENTER, text1 )
        ShotMode = 4
    
elseif (ShotMode == 2) then
        ShotMode = 3
text2 = "Storm Choice : Snow"
  self.Owner:PrintMessage( HUD_PRINTCENTER, text2 )


elseif (ShotMode == 3) then
        ShotMode = 1
text3 = "Storm Choice : Fire Storm"
  self.Owner:PrintMessage( HUD_PRINTCENTER, text3 )

elseif (ShotMode == 4) then
        ShotMode = 2
text4 = "Storm Choice : Lightning"
  self.Owner:PrintMessage( HUD_PRINTCENTER, text4 )
    end
    


end

N = 2000
UP = 2000
firerate = 100
firesize = 450
Start = 0
Away = 5.5

function FFR()            

for i= 1,20 do

Start = Start + 0.1
firesize = firesize * 0.95
firerate = firerate * 0.9
N = N * 0.9
UP = UP - 100
Away = Away + 0.07

        local FireRing = ents.Create("env_smokestack")
        FireRing:SetKeyValue("smokematerial", "effects/fire_cloud2.vmt")
        FireRing:SetKeyValue("rendercolor", "255 100 100" )
        FireRing:SetKeyValue("targetname","FireStorm")
        FireRing:SetKeyValue("basespread",N)
        FireRing:SetKeyValue("spreadspeed","10")
        FireRing:SetKeyValue("speed","100")
        FireRing:SetKeyValue("startsize",firesize)
        FireRing:SetKeyValue("endzide",firesize)
        FireRing:SetKeyValue("rate",firerate)
        FireRing:SetKeyValue("jetlength","100")
        FireRing:SetKeyValue("twist","900")
        FireRing:Spawn()
        FireRing:Fire("turnon","",Start)
        FireRing:Fire("Kill","",Away)
        FireRing:SetPos(hitpos + Vector(0,0,UP))
        end

    N = 2000
    Away = 5.5
    UP = 2000
    firerate = 100
    firesize = 350
    Start = 0
end


function FFRG()
    for i=0,2 do
        local sylsmoke = ents.Create("env_ar2explosion")
        sylsmoke:SetPos(hitpos)
        sylsmoke:SetKeyValue("material", "particles/fire_glow.vmt")
        sylsmoke:Fire("explode","",2)
        sylsmoke:Fire("Kill","",4)
        sylsmoke:Spawn()
    end
        local HurtPlace = ents.Create("point_hurt")
        HurtPlace:SetPos(hitpos)
        HurtPlace:SetKeyValue("DamageRadius", "250")
        HurtPlace:SetKeyValue("Damage", "60")
        HurtPlace:SetKeyValue("DamageDelay", "0.01")
        HurtPlace:SetKeyValue("DamageRadius", "400")
        HurtPlace:SetKeyValue("DamageType", "8")
        HurtPlace:Fire("turnon","",2)
        HurtPlace:Fire("kill","",6.2)
        HurtPlace:Spawn()

end



function SSS()

    local SS = ents.Create("env_smokestack")
        SS:SetKeyValue("smokematerial", "decals/light.vmt")
        SS:SetKeyValue("rendercolor", "255 255 255" )
        SS:SetKeyValue("angles","270")
        SS:SetKeyValue("basespread","1000")
        SS:SetKeyValue("spreadspeed","1000")
        SS:SetKeyValue("speed","100")
        SS:SetKeyValue("startsize","10")
        SS:SetKeyValue("endzide","40")
        SS:SetKeyValue("rate","6000")
        SS:SetKeyValue("jetlength","300")
        SS:SetKeyValue("twist","360")
        SS:Spawn()
        SS:Fire("turnon","",0.3)
        SS:Fire("Kill","",6)
        SS:SetPos(hitpos)

    
    local SSH = ents.Create("point_hurt")
        SSH:SetPos(hitpos)
        SSH:SetKeyValue("Damage", "0.1")
        SSH:SetKeyValue("DamageDelay", "0.01")
        SSH:SetKeyValue("DamageRadius", "1000")
        SSH:SetKeyValue("DamageType", "16384")
        SSH:Fire("turnon","",0)
        SSH:Fire("kill","",6.2)
        SSH:Spawn()
    


    end
function FSS()

    
        
        local FireStorm = ents.Create("env_smokestack")
        FireStorm:SetKeyValue("smokematerial", "effects/fire_cloud2.vmt")
        FireStorm:SetKeyValue("rendercolor", "255 100 100" )
        FireStorm:SetKeyValue("targetname","FireStorm")
        FireStorm:SetKeyValue("basespread","700")
        FireStorm:SetKeyValue("spreadspeed","100")
        FireStorm:SetKeyValue("speed","500")
        FireStorm:SetKeyValue("startsize","99")
        FireStorm:SetKeyValue("endzide","100")
        FireStorm:SetKeyValue("rate","300")
        FireStorm:SetKeyValue("jetlength","600")
        FireStorm:SetKeyValue("twist","900")
        FireStorm:Spawn()
        FireStorm:Fire("turnon","",0.3)
        FireStorm:Fire("Kill","",6)
        FireStorm:SetPos(hitpos)

        local Shaker = ents.Create("env_shake")
        Shaker:SetKeyValue("amplitude", "140")
        Shaker:SetKeyValue("radius", "10000" )
        Shaker:SetKeyValue("duration","5.6")
        Shaker:SetKeyValue("frequency","100")
        Shaker:SetKeyValue("spawnflags","8")
        Shaker:Spawn()
        Shaker:Fire("startshake","",0)
        Shaker:Fire("Kill","",6)
        Shaker:SetPos(hitpos)

    for i=0,2 do
        local sylsmoke = ents.Create("env_ar2explosion")
        sylsmoke:SetPos(hitpos)
        sylsmoke:SetKeyValue("material", "particles/fire_glow.vmt")
        sylsmoke:Fire("explode","1",0)
        sylsmoke:Fire("Kill","",4)
        sylsmoke:Spawn()
    end

        local HurtPlace = ents.Create("point_hurt")
        HurtPlace:SetPos(hitpos)
        HurtPlace:SetKeyValue("DamageRadius", "250")
        HurtPlace:SetKeyValue("Damage", "60")
        HurtPlace:SetKeyValue("DamageDelay", "0.01")
        HurtPlace:SetKeyValue("DamageRadius", "700")
        HurtPlace:SetKeyValue("DamageType", "8")
        HurtPlace:Fire("turnon","",0)
        HurtPlace:Fire("kill","",6.2)
        HurtPlace:Spawn()

for i = 1,100 do
local a = math.random(-500,500)
local b = math.random(-500,500)
local c = math.random(0,550)
local r = math.random(10,40) * .1
        local    explosions = ents.Create("env_explosion")

        explosions:SetPos(hitpos + Vector(a,b,c))
        explosions:SetKeyValue("iMagnitude","100")
        explosions:Spawn()
        explosions:Fire("explode","",r)
      explosions:Fire("kill","",1 + r)
end


-- remove the "--" if uwant little fire's on the ground then remove the -- for the next function... i dont like them..
--for i = 1,20 do
--local d = math.random(-1000,1000)
--local e = math.random(-1000,1000)
--local s = math.random(10,40) * .1
--      local    Firetrails = ents.Create("env_fire_trail")
--        Firetrails:SetPos(hitpos + Vector(d,e,0))
--        Firetrails:Spawn()
--      Firetrails:Fire("kill","",7.5 - s)
--end
        

        local    redglow = ents.Create("env_lightglow")
        redglow:SetPos(hitpos)
        redglow:SetKeyValue("rendercolor","255 0 0")
        redglow:SetKeyValue("VerticalGlowSize","75")
        redglow:SetKeyValue("HorizontalGlowSize","75")
        redglow:SetKeyValue("MinDist","0")
        redglow:SetKeyValue("MaxDist","1024")
        redglow:Spawn()
        redglow:Fire("kill","",5)

end

function LSSa()
            local    LT = ents.Create("info_target")
               LT:SetKeyValue("targetname","ground")
            LT:SetPos(hitpos + Vector(0,0,-100))
            LT:Fire("kill","",6.5)
            LT:Spawn()

            for i = 1,50 do 
                local r = math.random(10,45) * .10
                local    explosions = ents.Create("env_explosion")
                explosions:SetPos(hitpos)
                       explosions:SetKeyValue("iMagnitude","100")
                       explosions:Spawn()
                          explosions:Fire("explode","",1 + r)
                      explosions:Fire("kill","",2 + r)
        end

end
function LSSb()
            for i = 1,50 do

                 f = math.random(-2000,2000)
                 g = math.random(-2000,2000)
                local LT = ents.Create("info_target")
                       LT:SetKeyValue("targetname","ground")
                LT:SetPos(hitpos + Vector(f,g,1))
                LT:Fire("kill","",6.5)
                LT:Spawn()
                


            --    local    LS = ents.Create("env_spark")
               --        LS:SetKeyValue("maxdelay","0.5")
               --        LS:SetKeyValue("magnitude","2")
               --        LS:SetKeyValue("traillength","3")
               --        LS:SetKeyValue("spawnflags","18")
            --    LS:SetPos(hitpos + Vector(f,g,1))
            --    LS:Fire("kill","",6.3)
            --    LS:Fire("startspark","",1.8)
            --    LS:Spawn()
                

        

                local r = math.random(10,50) * .10
                local    explosions = ents.Create("env_explosion")
                explosions:SetPos(hitpos + Vector(f,g,1))
                       explosions:SetKeyValue("iMagnitude","100")
                       explosions:Spawn()
                          explosions:Fire("explode","",1 + r)
                      explosions:Fire("kill","",2 + r)


        end


            end
        
function LSS()

        
        local CL = ents.Create("env_steam")   
        CL:SetKeyValue("spreadspeed","1000")
        CL:SetKeyValue("speed","10")
        CL:SetKeyValue("startsize","1000")
        CL:SetKeyValue("endsize","1000")
        CL:SetKeyValue("rate","1000")
        CL:SetKeyValue("Jetlength","50")
        CL:SetKeyValue("angles","90")
        CL:SetKeyValue("rendercolor","100 100 100")
        CL:Fire("turnon","",0)
        CL:Fire("kill","",6.5)
        CL:Spawn()
        CL:SetPos(hitpos + Vector(0,0,2000))


            local Shaker = ents.Create("env_shake")
        Shaker:SetKeyValue("amplitude", "140")
        Shaker:SetKeyValue("radius", "10000" )
        Shaker:SetKeyValue("duration","6.5")
        Shaker:SetKeyValue("frequency","100")
        Shaker:SetKeyValue("spawnflags","8")
        Shaker:Spawn()
        Shaker:Fire("startshake","",0)
        Shaker:Fire("Kill","",7)
        Shaker:SetPos(hitpos)
            
            
            for i = 1,50 do
            timer.Simple(1.6,laserlight)
            local v = (math.random(-2000,2000))
            local vv = (math.random(-2000,2000))
            local vvv = (math.random(1950,1951))
                    local LA = ents.Create("env_laser")
                LA:SetKeyValue("lasertarget", "ground")
                LA:SetKeyValue("renderamt", "255")
                LA:SetKeyValue("renderfx", "15")
                LA:SetKeyValue("rendercolor", "0 100 255")
                LA:SetKeyValue("texture", "sprites/laserbeam.spr")
                LA:SetKeyValue("texturescroll", "35")
                LA:SetKeyValue("dissolvetype", "1")
                LA:SetKeyValue("spawnflags", "32")
                LA:SetKeyValue("width", "15")
                LA:SetKeyValue("damage", "50000")
                LA:SetKeyValue("noiseamplitude", "10")
                LA:Spawn()
                LA:Fire("Kill","",6)
                LA:Fire("turnoff","",0)
                LA:Fire("turnon","",1.8)
                LA:SetPos(hitpos + Vector(v, vv, vvv))
        end
            

end
            

    

function laserlight()
            local v = (math.random(-2000,2000))
            local vv = (math.random(-2000,2000))
            local vvv = (math.random(1950,1951))

                        local    LG = ents.Create("env_lightglow")
                        LG:SetPos(hitpos + Vector(v, vv, vvv))
                        LG:SetKeyValue("rendercolor","200 200 255")
                        LG:SetKeyValue("VerticalGlowSize","15")
                        LG:SetKeyValue("HorizontalGlowSize","15")
                        LG:SetKeyValue("MinDist","0")
                        LG:SetKeyValue("MaxDist","1024")
                        LG:SetKeyValue("OuterMaxDist","4000")
                        LG:Spawn()
                        LG:Fire("kill","",4.5)
    
end

Дальше исследуем и пишем своё. Можно даже не раскидывать свои тексты по разным папкам. Достаточно дублировать этот проект в ту же папку где он лежал, то есть Steam\steamapps\common\GarrysMod\garrysmod\addons и менять. Изменения будут отображаться в игре.

А поскольку аддонов десятки тысяч, то всегда найдётся что-то интересное.
Отредактировано 02.01.2018 16:38 velkin . Предыдущая версия . Еще …
Отредактировано 02.01.2018 16:29 velkin . Предыдущая версия .
Отредактировано 02.01.2018 16:27 velkin . Предыдущая версия .
Re[2]: Анимация природных явлений
От: VVV Россия  
Дата: 03.01.18 01:04
Оценка:
Здравствуйте, CEMb, Вы писали:

Спасибо!! Очень давно, ещё в DOSе делал огонь (думаю, все делали такое) — нулевая строка — рандомная (самая горячая), остальные строки вычисляются по предыдущей минус небольшое затухание кверху, ну и сдвиг влево/вправо.. Получается довольно хороший огонь.. Была надежда, что уже есть _алгоритмические_базы_ для таких симуляций. Типа, как есть же std::sort, который закрывает вопрос о сортировке (не для холивара эти слова — std::sort и вправду хорош для _большинства_ случаев).
Но поиск показал, что пока такого волшебного зелья, увы, нет. Есть неплохие реализации, но достигаются они путём скрупулёзного _подбора_ параметров в одном конкретном случае.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.