Автор Тема: Рейтрейсер для анимации на GPU.  (Прочитано 27250 раз)

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #105 : 31 Июль 2016, 23:36:06 »
Ладно. Понял тебя. Давай только без обоюдных обид. Думал,что синтаксис FreeBasic очень близок к базовому английскому, потому и подумал, что тебе будет просто врубиться в его код, пару раз заглянув в справку, ссылку на которую я давал в теме по Freebasic. То что ты согласился, должно было меня насторожить...
В общем, попробую сам написать на Си и протестировать скорость. Если скорость окажется той же, то забью на Си до поры до времени Один хрен для меня ООП - темный лес на чужой планете, а процедурное программирование вполне себе шустрый машинный код выдает и с помощью FreeBasic+Assembler... хотя, может меня приколет Си... надо пробовать :)
« Последнее редактирование: 01 Август 2016, 00:00:24 от Samovar »

Оффлайн LanuHum

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #106 : 31 Июль 2016, 23:40:56 »
Цитировать
В общем, попробую сам написать на Си.
Сказать честно, поняв твою цель, у меня и нет желания портировать её. Это лишние знания. Завтра я буду учиться ЧПУ, а послезавтра буду искать, почему я время не могу померять в этой грёбаной проге. :)

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #107 : 01 Август 2016, 00:13:55 »
Оставлю это здесь.
http://ru.stackoverflow.com/questions/440326/Как-измерить-скорость-работы-программы
Более чем уверен, что это пригодится, если хочется замутить рендерер х50 раз шустрее Суслика :)

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #108 : 01 Август 2016, 18:13:52 »
LanuHum, ты оказался прав на счёт graphics.h Мои извинения, если я тебя задел вчера. Оказалось, что библиотека шла с Bolrand C++ и в стандарт не входит. Но её изучают в ВУЗ почему-то :) Мне с трудом удалось найти способ подключить её под Code::Blocks http://forinformatics.blogspot.ru/2014/04/code-blocks.html на английском http://www.codewithc.com/how-to-include-graphics-h-in-codeblocks/
Вот чего пишут про Linux (англ.) https://mandeepsimak.wordpress.com/2012/02/29/graphics-h-in-linux-for-cc/
Кстати нарисовал миллион пикселей на С++ с помощью этого... даже таймер не пришлось подключать. Очень медленно, потому что без аппаратного ускорения, видимо...



А чем тебя SDL не устраивает?
« Последнее редактирование: 01 Август 2016, 18:18:26 от Samovar »

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #109 : 01 Август 2016, 18:22:45 »
Если интересно, то вот простейший рендерер на фотонах (Freebasic): http://www.freebasic.net/forum/viewtopic.php?f=7&t=15154
Видео автора https://www.youtube.com/playlist?list=PL1EE5A9A3594BFDCF
В теме несколько вариантов, этот последний:

Код

' PhotonMapping


#ifndef true
#define true -1
#define false 0
  #endif


Type float As single 'double


Const As Integer xDimension          = 512
Const As Integer yDimension          = 512
Const As Integer nTypes              = 2 ' two types of objects sphere and plane
Const As Integer MaxPhotons          = 200
Const As Integer MaxPhotonRefections = 1
Const As float  PhotonSize           = 0.1
Const As float gInverseSquared       = 1.0 / PhotonSize * PhotonSize
Const As float  MilliSeconds         = 500
Const As float gExposure             = 1.0 / (1000 / MilliSeconds)
Const As Integer MaxRaytraceRefections = 12


#define nSpheres 3 ' number of spheres
#define nPlanes  6 ' number of planes (a box)
Dim Shared As float Ratio
Dim Shared As Integer gNObjects(1) = {nSpheres,nPlanes&}
Dim Shared As float  gAmbient      = 0
Dim Shared As float  gOrigin(2)
Dim Shared As float  gLight(2)     = {0,1.0,4} 'x,y,z position


Dim Shared As float  gSpheres(nSpheres-1,3) =  {_
                            {-1.0,-1.0,4.0, 0.5} , _
                            { 6.4, 0.0,2.8, 5.0} , _
                            { 1.0,-1.0,4.0, 0.5}}
                             ' x,y,z, position and radius


Dim Shared As float  gPlanes(nPlanes-1,1)  = {_
                                      {0,  1.5}, _
                                      {0, -1.5}, _
                                      {1, -1.5}, _
                                      {1,  1.5}, _
                                      {2,  5.0}, _
                                      {2, -1.0}}


Dim Shared As Integer NumberOfPhotons(1,5)
Dim Shared As float   gPhotons(nTypes,nPlanes+nSpheres, _
                               MaxPhotons + MaxPhotons*MaxPhotonRefections, _
                               2,2) '3 * x,y,z
Dim Shared As Integer gIntersect
Dim Shared As Integer gType
Dim Shared As Integer gIndex
Dim Shared As float   gDist2,gDist
Dim Shared As float   gPoint(2)


Function min(a As float ,b As float ) As float
  If b<a Then Return b
  Return a
End Function


Function max(a As float ,b As float ) As float
  If b>a Then Return b
  Return a
End Function


Function rnd2 As float
  Return (Rnd-Rnd)
End Function


Function SquaredDistance(a() As float , _
                         b() As float , _
                         d2 As float ) As Integer
  Dim As float  ab = a(0) - b(0)
  Dim As float  d = ab*ab
  If (d > d2) Then Return false
  ab = a(1) - b(1)
  d += ab*ab
  If (d > d2) Then Return false
  ab = a(2) - b(2)
  d += ab*ab
  If (d > d2) Then Return false
  gDist2 = d
  Return true
End Function


Sub SurfaceNormal(r() As float , _
                  typ As Integer, _
                  idx As Integer, _
                  HitPoint() As float , _
                  O() As float )
  Dim As float  Normal(2),L
  If (typ = 0) Then
    Normal(0)=HitPoint(0)-gSpheres(idx,0)
    Normal(1)=HitPoint(1)-gSpheres(idx,1)
    Normal(2)=HitPoint(2)-gSpheres(idx,2)
  Elseif (typ = 1) Then
    Dim As Integer axis = gPlanes(idx,0)
    Normal(axis) = O(axis) - gPlanes(idx,1)
  Else
    'beep
  End If
  l=Normal(0)*Normal(0) _
   +Normal(1)*Normal(1) _
   +Normal(2)*Normal(2)
  If l Then l=1/Sqr(l)
  r(0)=Normal(0)*l
  r(1)=Normal(1)*l
  r(2)=Normal(2)*l
End Sub


Sub Mirror2(Ret()       As float, _
            Direction() As float, _
            HitPoint()  As float, _
            Normale()   As float)
  Dim As float L
  HitPoint(0)+=Direction(0)*-0.1
  HitPoint(1)+=Direction(1)*-0.1
  HitPoint(2)+=Direction(2)*-0.1
  L = Normale(0)*Direction(0) _
    + Normale(1)*Direction(1) _
    + Normale(2)*Direction(2)
  L*=-2
  Ret(0)=Direction(0)+L*Normale(0)
  Ret(1)=Direction(1)+L*Normale(1)
  Ret(2)=Direction(2)+L*Normale(2)
End Sub


Sub MirrorVec(Ret()       As float ,_
              Direction() As float , _
              Origin()    As float )
  Dim As float  L,Normale(2)
  SurfaceNormal(Normale(),gType, gIndex, gPoint(), Origin())
  gPoint(0)+=Direction(0)*-0.1
  gPoint(1)+=Direction(1)*-0.1
  gPoint(2)+=Direction(2)*-0.1
  L = Normale(0)*Direction(0) _
    + Normale(1)*Direction(1) _
    + Normale(2)*Direction(2)
  L*=-2
  Ret(0)=Direction(0)+L*Normale(0)
  Ret(1)=Direction(1)+L*Normale(1)
  Ret(2)=Direction(2)+L*Normale(2)


End Sub


'
' Raytracing
'
Sub Raytrace(RayDirection() As float ,RayOrigin() As float )
  gIntersect = false
  gDist      = 999999.9
 
  If gNObjects(1)>0 Then
    For idx As Integer =0 To gNObjects(1)-1
      Dim As Integer axis = gPlanes(idx,0)
      If RayDirection(axis)<>0 Then
        Dim As float  l = (gPlanes(idx,1) - RayOrigin(axis)) / RayDirection(axis)
        If (l>0) And (l<gDist) Then
          gType  = 1
          gIndex = idx
          gDist  = l
          gIntersect = true
        End If
      End If
    Next
  End If
 
  If gNObjects(0)>0 Then
    Dim As float  SphereDirection(2)
    Dim As float  A = RayDirection(0)*RayDirection(0) _
                    + RayDirection(1)*RayDirection(1) _
                    + RayDirection(2)*RayDirection(2)
                  A+=A
    For idx As Integer =0 To gNObjects(0)-1
      SphereDirection(0)=RayOrigin(0)-gSpheres(idx,0)
      SphereDirection(1)=RayOrigin(1)-gSpheres(idx,1)
      SphereDirection(2)=RayOrigin(2)-gSpheres(idx,2)
      Dim As float  R = gSpheres(idx,3)*gSpheres(idx,3)
      Dim As float  B = SphereDirection(0)*RayDirection(0) _
                      + SphereDirection(1)*RayDirection(1) _
                      + SphereDirection(2)*RayDirection(2)
                    B+=B
                   
      Dim As float  C = SphereDirection(0)*SphereDirection(0) _
                      + SphereDirection(1)*SphereDirection(1) _
                      + SphereDirection(2)*SphereDirection(2)
                    C-=R
      Dim As float  D = B*B - 2*A*C
      If (D>0.0) Then
        Dim As float  sign  = iif(C < -0.0001,1.0,-1.0)
        Dim As float  l = (-B + sign*Sqr(D))/A
        If (l>0.0) And (l<gDist) Then
          gType      = 0
          gIndex     = idx
          gDist      = l
          gIntersect = true
        End If
      End If
    Next
  End If
End Sub


Sub AbsorbColor(ret()   As float , _
                rgbIn() As float , _
                r As float ,g As float ,b As float )
  Dim As float  rgbOut(2)={r,g,b}
  For c As Integer =0 To 2
    If rgbOut(c)<rgbIn(c) Then
      ret(c)=rgbOut(c)
    Else
      ret(c)=rgbIn(c)
    End If
  Next
End Sub


Sub GetColor(r() As float , _
            rgbIn() As float , _
            typ As Integer, _
            idx As Integer)


  If (typ=0) Then     ' spheres
    If idx=0 Then
      AbsorbColor(r(),rgbIn(), 0.0,0.0,0.0)
    Elseif idx=1 Then
      AbsorbColor(r(),rgbIn(), 0.0,0.0,0.0)
    elseif idx=2 then
      AbsorbColor(r(),rgbIn(), 0.2,0.2,0.
    End If
  Elseif (typ=1) Then ' planes
    If idx=0 Then
      AbsorbColor(r(),rgbIn(), 0.1, 0.8, 0.1) ' right
    Elseif idx=1 Then
      AbsorbColor(r(),rgbIn(), 0.8, 0.1, 0.1) ' left
    Elseif idx=2 Then
      AbsorbColor(r(),rgbIn(), 0.5, 0.5, 0.0) ' floor
    Elseif idx=3 Then
      AbsorbColor(r(),rgbIn(), 0.2, 0.2, 0.2) ' ceil
    Elseif idx=4 Then
      AbsorbColor(r(),rgbIn(), 0.0, 0.0, 0.0) ' front
    Elseif idx=5 Then
      AbsorbColor(r(),rgbIn(), 0.0, 0.0, 0.0) ' behind camera
    End If
  End If
End Sub


'
' Photon Mapping
'
Sub GatherPhotons(energy() As float , _
                  HitPoint() As float , _
                  typ As Integer, _
                  idx As Integer)
  Dim As float  N(2)
  Dim As float  v(2)
  Dim As float  weight
  Dim As float  frgb(2)
  SurfaceNormal(N(), typ, idx, HitPoint(), gOrigin())


  For i As Integer = 0  To  NumberOfPhotons(typ,idx)-1
    ' photon location
    v(0)=gPhotons(typ,idx,i,0,0)
    v(1)=gPhotons(typ,idx,i,0,1)
    v(2)=gPhotons(typ,idx,i,0,2)
    ' in the near of an active photon ?
    If (SquaredDistance(HitPoint(),v(),gInverseSquared)) Then
      ' photon direction
      Dim As float  cosin = N(0)*gPhotons(typ,idx,i,1,0) _
                          + N(1)*gPhotons(typ,idx,i,1,1) _
                          + N(2)*gPhotons(typ,idx,i,1,2)
      weight = max(0.0, -cosin)
      if weight then
        weight *= (1.0 - sqr(gDist2)) * gExposure
        if weight then
          ' photon energy
          frgb(0)+=gPhotons(typ,idx,i,2,0)*weight
          frgb(1)+=gPhotons(typ,idx,i,2,1)*weight
          frgb(2)+=gPhotons(typ,idx,i,2,2)*weight
        end if
      end if
    End If
  Next
  For j As Integer=0 To 2
    energy(j)=max(0,min(1,frgb(j) ) )
  Next
End Sub


Sub StorePhoton(typ As Integer, _
                idx As Integer, _
                l() As float ,_
                d() As float , _
                e() As float )
  Dim As Integer Photon=NumberOfPhotons(typ,idx)
 
  For i As Integer=0 To 2
    gPhotons(typ,idx,Photon,0,i) = l(i) ' Location
    gPhotons(typ,idx,Photon,1,i) = d(i) ' Direction
    gPhotons(typ,idx,Photon,2,i) = e(i) ' Energy
  Next
  NumberOfPhotons(typ,idx)=Photon+1
End Sub


Sub ShadowPhoton(RayDirection() As float )
  static As float  BumpedPoint(2)
  static As float  ShadowPoint(2)
  Static As float ShadowEnerg(2) = {-0.2,-0.2,-0.2}
  Dim As float   OldPoint(2) = {gPoint(0), gPoint(1),gPoint(2)}
  Dim As Integer OldType     = gType
  Dim As Integer OldIndex    = gIndex
  Dim As float   OldDist     = gDist
 
  BumpedPoint(0)=gPoint(0)+RayDirection(0)*0.000001
  BumpedPoint(1)=gPoint(1)+RayDirection(1)*0.000001
  BumpedPoint(2)=gPoint(2)+RayDirection(2)*0.000001


  Raytrace(RayDirection(), BumpedPoint())


  ShadowPoint(0)=BumpedPoint(0)+RayDirection(0)*gDist
  ShadowPoint(1)=BumpedPoint(1)+RayDirection(1)*gDist
  ShadowPoint(2)=BumpedPoint(2)+RayDirection(2)*gDist


  StorePhoton(gType, gIndex, ShadowPoint(), RayDirection(), ShadowEnerg())


  gPoint(0) = OldPoint(0)
  gPoint(1) = OldPoint(1)
  gPoint(2) = OldPoint(2)
  gType     = OldType
  gIndex    = OldIndex
  gDist     = OldDist


End Sub


Sub EmitPhotons
  randomize 1 'timer
  dim As float PhotonEnergy(2)
  dim As float PhotonDirection(2)
  dim As float PhotonOrigin(2),l
  For typ As Integer = 0 To nTypes-1
    For idx As Integer = 0 To gNObjects(typ)-1
      NumberOfPhotons(typ,idx) = 0
    Next
  Next
  For i As Integer = 0 To MaxPhotons-1
    Dim As Integer Reflection = 0
    ' random photon Energy
    PhotonEnergy(0)=rnd
    PhotonEnergy(1)=rnd
    PhotonEnergy(2)=rnd
#if 0
    ' normalize energy
    l = PhotonEnergy(0)*PhotonEnergy(0) _
      + PhotonEnergy(1)*PhotonEnergy(1) _
      + PhotonEnergy(2)*PhotonEnergy(2)
    if l then
      l=1.0/sqr(l)
      PhotonEnergy(0)*=l
      PhotonEnergy(1)*=l
      PhotonEnergy(2)*=l
    end if
#endif


    ' radom photon Direction
    PhotonDirection(0)= rnd2
    PhotonDirection(1)= rnd2*2
    PhotonDirection(2)= rnd2
#if 0
    ' normalize direction
    l = PhotonDirection(0)*PhotonDirection(0) _
      + PhotonDirection(1)*PhotonDirection(1) _
      + PhotonDirection(2)*PhotonDirection(2)
    if l then
      l=1.0/sqr(l)
      PhotonDirection(0)*=l
      PhotonDirection(1)*=l
      PhotonDirection(2)*=l
    end if
#endif


    ' photon position origin from light
    PhotonOrigin(0)=gLight(0)
    PhotonOrigin(1)=gLight(1)
    PhotonOrigin(2)=gLight(2)


    Raytrace(PhotonDirection(), PhotonOrigin())
    While (gIntersect<>0) And (Reflection < MaxPhotonRefections)
      Reflection+=1
      gPoint(0)=PhotonOrigin(0)+PhotonDirection(0)*gDist
      gPoint(1)=PhotonOrigin(1)+PhotonDirection(1)*gDist
      gPoint(2)=PhotonOrigin(2)+PhotonDirection(2)*gDist
      GetColor(PhotonEnergy(),PhotonEnergy(),gType,gIndex)
#if 0
      Dim As float l=1.0/Reflection
      PhotonEnergy(0)*=l
      PhotonEnergy(1)*=l
      PhotonEnergy(2)*=l
#endif
      StorePhoton(gType, gIndex, gPoint(), PhotonDirection(),PhotonEnergy())
      ShadowPhoton(PhotonDirection())
      MirrorVec(PhotonDirection(),PhotonDirection(),PhotonOrigin())
      Raytrace(PhotonDirection(), gPoint())
      PhotonOrigin(0)=gPoint(0)
      PhotonOrigin(1)=gPoint(1)
      PhotonOrigin(2)=gPoint(2)
    Wend
  Next
End Sub


Sub GetPixelColor(PixelRGB() As float , _
                  x As float ,y As float , z As float=1)
  Dim As float  RayDirection(2) = {x,y,z}
  Raytrace(RayDirection(), gOrigin())
  If (gIntersect) Then
    gPoint(0)=gOrigin(0)+RayDirection(0)*gDist
    gPoint(1)=gOrigin(1)+RayDirection(1)*gDist
    gPoint(2)=gOrigin(2)+RayDirection(2)*gDist
    GatherPhotons(PixelRGB(),gPoint(),gType,gIndex)
   ' If gType=0 or gIndex>3 Then
    Dim As Integer nDivs=0,nReflection=0
    Dim As float  MirrorsRGB(2)
    While ((gType=0 And gIndex<2) Or gIndex>3) And gIntersect And _
          (nReflection<MaxRaytraceRefections)
      nReflection+=1
      MirrorVec(RayDirection(),RayDirection(),gOrigin())
      Raytrace(RayDirection(), gPoint())
      If (gIntersect) Then
        Dim As float  MirRGB(2)
        nDivs+=1
        gPoint(0)+=RayDirection(0)*gDist
        gPoint(1)+=RayDirection(1)*gDist
        gPoint(2)+=RayDirection(2)*gDist
        GatherPhotons(MirRGB(),gPoint(),gType,gIndex)
        MirrorsRGB(0)+=MirRGB(0)
        MirrorsRGB(1)+=MirRGB(1)
        MirrorsRGB(2)+=MirRGB(2)
      End If
    Wend
    If nDivs>0 Then
      MirrorsRGB(0)/=nDivs
      MirrorsRGB(1)/=nDivs
      MirrorsRGB(2)/=nDivs
      PixelRGB(0)=PixelRGB(0)*0.25+MirrorsRGB(0)*0.75
      PixelRGB(1)=PixelRGB(1)*0.25+MirrorsRGB(1)*0.75
      PixelRGB(2)=PixelRGB(2)*0.25+MirrorsRGB(2)*0.75
    End If
   
    'End If
  Else
    PixelRGB(0)=1 ' !!! debug only !!!
    PixelRGB(1)=0
    PixelRGB(2)=1
  End If
End Sub




Sub Render
  Dim As Integer h,m,s,l,t
  dim as float b(2),x,y
  Dim As Double t1=Timer
  WindowTitle " PhotonMapper rendering ..."
  for t =0 to yDimension-1
    Y = -(t/yDimension - 0.5)
    screenlock
    for l =0 to xDimension-1
      X =  (l/xDimension - 0.5)*Ratio
      GetPixelColor(b(),x,y)
      pset (l,t),rgb(b(0)*255,b(1)*255,b(2)*255)
    next
    screenunlock
  next
  s=timer-t1:h=s\3600:s-=h*3600:m=s\60:s-=m*60
  WindowTitle "PhotonMapper done " & h & ":" & m & ":" & s
End Sub


'
' main
'
Ratio= iif(xDimension>yDimension, _
           xDimension/yDimension, _
           yDimension/xDimension)


Randomize Timer
ScreenRes xDimension,yDimension,24
EmitPhotons
Render
'Bsave "PhotonMapper.bmp",0
Sleep
« Последнее редактирование: 01 Август 2016, 18:35:20 от Samovar »

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #110 : 01 Август 2016, 20:45:34 »

То что у меня вышло на Си :) Тяжеловато врубаться...
Код
#include <graphics.h>
#include <stdio.h>


int main( void)
{
    //---------- Инициализация графики ----------//
    int gdriver = DETECT, gmode, errorcode;
    initgraph(&gdriver,&gmode,"");
    //---------- Конец инициализации -----------//


    for (int i = 0; i < 1000000; i++)
    {
        putpixel(rand()%640,rand()%500,rand()%0xFFFF);
    }


    printf("End");


return 0;
}

Оффлайн LanuHum

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #111 : 01 Август 2016, 23:04:23 »
Да я вполне согласен, что код FreеBasic может уступать коду С++, хотя компилятор  gcc у обоих один и тот же :) Вообще речь не об этом... мне ж тоже интересно врубиться в Си.
Я не вижу, что у freebasic  в линуксе компилятор gcc. Отдельный пакет с бинарником fbc Для компиляции он и зызывается. В gcc для компиляции С++ кода используются оптимизации, которые ускоряют процесс, но по умолчанию отключены. Оптимизируется код freebasic или нет, я не знаю.

Не думаю, что ты начал с простого. Вернее, может, и с простого, но закончится это ещё одной сторонней либой по рисованию окон. Одно дело пиксели покрасить, а другое дело, файловый диалог вызвать, чтобы выбрать файл для рендера, и пошло поехало...

SDL - либа слабая. Я не видел ни скроллеров в ней, ни сплиттеров. Её используют многие для вывода картинки рендера, но, у меня виды на будущее.
Я выбрал либу с большИм числом виджетов. В прок! :) Чтоб не переписывать потом, и не изобретать велосипед в поисках чего-то типа graphics.h. К фоксу я нашёл либу, использующую векторную графику Cairo, с помощью которой можно крутилки красивые нарисовать, как это делает GTK.

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #112 : 01 Август 2016, 23:45:44 »
Цитировать
Я не вижу, что у freebasic  в линуксе компилятор gcc
Вообще используется https://ru.wikipedia.org/wiki/GNU_Binutils

Внешние библиотеки (есть и Cairo)
http://free-basic.ru/helprus/ExtLibTOC.html

Полная русская справка тут: http://free-basic.ru/helprus/DocToc.html

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

Цитировать
Не думаю, что ты начал с простого. Вернее, может, и с простого, но закончится это ещё одной сторонней либой по рисованию окон. Одно дело пиксели покрасить, а другое дело, файловый диалог вызвать, чтобы выбрать файл для рендера, и пошло поехало...
Да графический интерфейс можно любой навестить, как сделано в  Pov-ray под Win... дело же не в нём, а в самом рендерере :)

Пиши на Cи, не вопрос... Freebasic просто проще... Может кому-то эта инфа по Freebasic пригодится, для своих маленьких прог, генераторов и утилит.

Завтра, если время будет, попробую "лиса" прикрутить к Code::Blocks и твой пример глянуть...

Кстати, в том примере с  пикселями у меня используется DirectX, потому так шустро... у тебя по идее это должен быть X11
« Последнее редактирование: 01 Август 2016, 23:56:35 от Samovar »

Оффлайн sungreen

  • ...
  • Житель
  • Kostroma mon amour
    • sungreen.github.io
Re: Рейтрейсер для анимации на GPU.
« Ответ #113 : 02 Август 2016, 06:15:38 »
>> Кстати, в том примере с  пикселями у меня используется DirectX, потому так шустро... у тебя по идее это должен быть X11
... наверное даже не x11, а opengl ...
Для Кота

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #114 : 02 Август 2016, 08:14:17 »
>> Кстати, в том примере с  пикселями у меня используется DirectX, потому так шустро... у тебя по идее это должен быть X11
... наверное даже не x11, а opengl ...
хрен его знает  :) ... хотя, да, прочёл невнимательно...в справке так и написано: http://free-basic.ru/helprus/GfxLib.html

Вот "пиксели" Freebasic на OpenGL (ещё в 2 раза шустрее почему-то):
Код
' Интеграция OpenGL
#INCLUDE Once "GL/gl.bi"
'#INCLUDE Once "GL/glu.bi"

' Определение констант, которые важны для экрана
Const scrnX = 800
Const scrnY = 600
Const depth = 32
Const fullscreen = &h0           ' Полноэкранный режим ( &h0 = обычный, &h1 = полноэкранный )
Dim As String driver: Dim As Integer i: Dim As Double start
Screenres scrnX,scrnY,depth,,&h2 Or fullscreen '&h2 = режим OpenGL
ScreenInfo ,,,,,, driver
' Конфигурация OpenGL
glMatrixMode(GL_PROJECTION)      ' Определение матрицы
glLoadIdentity
glViewport(0,0,scrnX,scrnY)      ' Установка оси координат
glOrtho(0,scrnX,scrnY,0,-128,128)
glMatrixMode(GL_MODELVIEW)       ' Отключить вывод невидимых частей
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
'glEnable GL_TEXTURE_2D           ' Включение текстур
'glLoadIdentity
'glEnable(GL_DEPTH_TEST)          ' Тест глубины
'glDepthFunc(GL_LESS)
'glEnable(GL_ALPHA_TEST)          ' Тест Альфа
'glAlphaFunc(GL_GREATER, 0.1)

Do
   glClear  GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT 'очищаем экран
   '  !! здесь различные команды !!
   start = Timer
   'glPointSize (rnd*10) 'размер точки
   glBegin (GL_POINTS)
      For i = 1 To 1000000   
         glColor3f (Rnd,Rnd,Rnd) ' RGB цвет в формате 0 до 1
         glVertex2f (Rnd*scrnX, Rnd*scrnY) ' рисуем точку
      Next i
   glEnd
   WindowTitle "Driver: "+driver+"  Time: "+Str(Timer-start)
   '  !! здесь различные команды !!
   glFlush ' Обработка команд
   Flip
Loop Until MultiKey(&h01) ' Выход из цикла при нажатии Esc
« Последнее редактирование: 02 Август 2016, 08:19:10 от Samovar »

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #115 : 02 Август 2016, 11:14:14 »
Цитировать
SDL - либа слабая. Я не видел ни скроллеров в ней, ни сплиттеров. Её используют многие для вывода картинки рендера, но, у меня виды на будущее.
Я выбрал либу с большИм числом виджетов. В прок! :) Чтоб не переписывать потом, и не изобретать велосипед в поисках чего-то типа graphics.h. К фоксу я нашёл либу, использующую векторную графику Cairo, с помощью которой можно крутилки красивые нарисовать, как это делает GTK.
Ланухумыч, ты сильно только не обижайся  :), но я тебе ещё раз напомню про твою задумку с GUI. Пока даже непонятна суть рендерера, который ты планируешь. На сей раз с помощью видео: https://www.youtube.com/watch?v=OvAHirMoUWk
Увы, выглядит это именно так... надеюсь, начинка сначала будет написана, а до нее план, как советовали раньше :)

Оффлайн LanuHum

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #116 : 02 Август 2016, 18:04:51 »
Samovar, ты мне объясни, почему для теста ты выбрал перерисовку пикселов?
Почему ты не взял просто какое-нибудь математическое действие, выполняемое миллион раз?
Дело в том, что я своей бестолковкой сразу связал перерисовку пикселов  с процессом, который рано или поздно востребуется в рендере.
Я не знаю, почему некоторые делают вывод изображения в опенгл или директ-икс , а не простой просмотрщик изображений. Какие-то инициализации, 2Д текстуры. Если это задействует видеокарту, то на мой взгляд, это плохо. Карта нам будет нужна для вычислений рэйтрэйсинга, и нагружать её выполнением вспомогательных функций, кажется нецелесообразным.
Теперь про саму задумку. То бишь, чего хочется-то? В противоположность тенденции писать unbias - физически точное, мне хочется написать bias - физически приблизительное с двумя решающими критериями:
1. скорость максимальная
2. потребление ресурсов минимальное.
Я уже ни раз упоминал Art Of Illusion. Вот там максимальная скорость, то бишь удовлетворяется первое требование. Второе требование прога не выполняет, вообще. Она не в состоянии разумно распоряжаться оперативной памятью компьютера. Povray умеет очень хорошо распоряжаться памятью компьютера, зато у него нет той скорости, которой обладает Art Of Illusion.
Посему поэтому сначала необходимо безо всяких планов на будущее тупо разобраться с алгоритмами рэйтрэйсинга и понять: как достигается скорость и как достигается экономичность на практике.
Почему я выбрал С++?
1. Всегда можно найти место на просторах сети, где подскажут конкретно по существу проблемы, потому что достаточное количество литературы и примеров.
2. Указатели и ссылки - это реально круто. Манипуляция данными происходит по адресам этих данных в оперативке. В этом зарыта скорость выполнения.
3. ООП разгружает мозг, раскладывая всё по полочкам. Я поверил на слово Страуструпу, когда прочитал в книге его рекомендации почему не стоит использовать С там, где это совсем не требуется, почему не стоит на С++ писать как на С, используя структуры, отказываясь от классов и тому подобное...

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #117 : 02 Август 2016, 21:25:08 »
Цитировать
Samovar, ты мне объясни, почему для теста ты выбрал перерисовку пикселов?
Почему ты не взял просто какое-нибудь математическое действие, выполняемое миллион раз?
Дело в том, что я своей бестолковкой сразу связал перерисовку пикселов  с процессом, который рано или поздно востребуется в рендере.
sungreen навёл на мысль, но согласен можно было протестировать математику на проце без сопроцессора, на проце с использованием сопроцессора... это просто для наглядности, хотя в итоге, ради расчёта цвета конкретного пикселя весь процесс рендеринга и затевается... но писать его, естественно, надо в какой-то иной кусок памяти, а затем иногда выводить этот кусок памяти или его фрагмент  в видеобуфер для просмотра, чего там делается - быстрее всего это будет, вероятно, с помощью OpenGL.
В том же Lux, если не ошибаюсь, этот процесс можно регулировать крутилкой, задавая время обновления картинки.




Цитировать
Посему поэтому сначала необходимо безо всяких планов на будущее тупо разобраться с алгоритмами рэйтрэйсинга и понять: как достигается скорость и как достигается экономичность на практике.
Но вообще, хотелось бы, что бы ты уж что-то начал. Так даже будет проще врубиться.
1. создал бы камеру и описал её положение, направление и прочие свойства типа перспективы и т.п. а так же привязал её к размеру визуализируемого изображения.
2. создал простейший объект типа треугольника в пространстве, описав координаты его вершин и нормаль
3. запустил сканирующий луч из камеры, и проверял бы его на пересечение с этим треугольником, рисуя чёрные точки, если луч не пересекается с треугольником и белые, когда пересекается. Но перед этим проверил бы, находится ли треугольник в поле видимости камеры (в пирамиде камеры). Если нет, то незачем проверять его на пересечение с лучом.
Это будет простейший Camera Ray или Первичный луч и в итоге должно получится изображение альфа канала без сглаживания... а дальше начнёшь потихоньку усложнять, прикрутив, возможно, сглаживание...учитывая расстояние, которое прошёл луч до пересечения, получишь Z-буфер... и так, потихоньку, помаленьку начнёт приходить понимание, как эти процессы можно оптимизировать...
« Последнее редактирование: 02 Август 2016, 22:17:21 от Samovar »

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #118 : 03 Август 2016, 01:44:40 »
По пункту 1: http://gamesmaker.ru/programming/directx/virtualnaya-kamera-perspektivnaya-proekciya/ 2 части + исходники
ещё инфы тут в самом начале http://www.enlight.ru/faq3d/articles/11.htm

По пункту 2: можешь экспортировать объект из Блендера в формат .raw (это список ХYZ вершин треугольников по порядку) и написать простенькую функцию его чтения в массив.

По пункту 3: пока не нашел примеров пересечения, может кто-то подскажет ссылки на то, как найти пересечение луча с плоскостью? По проверке на видимость в пирамиде камеры есть тут: http://pmg.org.ru/nehe/nehex2.htm

Оффлайн Samovar

  • Житель
Re: Рейтрейсер для анимации на GPU.
« Ответ #119 : 03 Август 2016, 02:11:47 »
Мимоходом нарвался на скрипт для blender 2.4х, который экспортирует в OpenGL Си... нихрена пока не разобрался как он должен работать... Есть ли подобный для текущих версий Блендера?


Скрипт:

Код
#!BPY

"""
Name: 'Objective-C Header (.h)'
Blender: 244
Group: 'Export'
Tooltip: 'Exports .h file for use with OpenGL ES - Modified by Jody McAdams (jmcadams@digipen.edu).  Original from iphonedevelopment.blogspot.com'
"""
import Blender
from Blender import *
import bpy
import bpy
import os

       
def write_obj(filepath):   
    out = file(filepath, 'w')
    sce = bpy.data.scenes.active
    ob = sce.objects.active
    mesh = Mesh.New()       
    mesh.getFromObject(ob.name)

    editmode = Window.EditMode()
    if editmode: Window.EditMode(0)
    has_quads = False
    for f in mesh.faces:
        if len(f) == 4:
            has_quads = True
            break
   
    if has_quads:
        oldmode = Mesh.Mode()
        Mesh.Mode(Mesh.SelectModes['FACE'])
       
        mesh.sel = True
        tempob = sce.objects.new(mesh)
        mesh.quadToTriangle(0) # more=0 shortest length
        oldmode = Mesh.Mode(oldmode)
        sce.objects.unlink(tempob)
       
        Mesh.Mode(oldmode)
   
    objectname = ob.getData(True)
    basename = objectname.capitalize()

    out.write('#import "GraphicsTypes.h"\n\n\n')
       
    if (mesh.faceUV):
        out.write('static const TexturedVertexData3D %sVertexData[] = {\n' % basename)
        for face in mesh.faces:
            for (vert, uvert) in zip(face.verts, face.uv):
                out.write('\t{/*v:*/{%f, %f, %f}, ' % (vert.co.x, vert.co.z, -vert.co.y) )
                out.write('/*n:*/{%f, %f, %f}, ' % (vert.no.x, vert.no.z, -vert.no.y))
                out.write('/*t:*/{%f, %f}' % ( uvert.x, 1.0-uvert.y ) )
                out.write('},\n')
        out.write('};\n\n')
    elif (mesh.vertexColors):
        out.write('static const ColoredVertexData3D %sVertexData[] = {\n' % basename)
        for face in mesh.faces:
            for (vert, color) in zip(face.verts, face.col):
                out.write('\t{/*v:*/{%f, %f, %f}, ' % (vert.co.x, vert.co.z, -vert.co.y) )
                out.write('/*n:*/{%f, %f, %f}, ' % (vert.no.x, vert.no.z, -vert.no.y))
                out.write('/*c:*/{%f, %f, %f, %f}' % ( color.r / 255.0, color.g / 255.0, color.b / 255.0, color.a / 255.0) )
                out.write('},\n')
        out.write('};\n\n')
    else:
        out.write
        out.write('static const VertexData3D %sVertexData[] = {\n' % basename)
        for face in mesh.faces:
            for vert in face.verts:
                out.write('\t{/*v:*/{%f, %f, %f}, ' % (vert.co.x, vert.co.z, -vert.co.y) )
                out.write('/*n:*/{%f, %f, %f} ' % (vert.no.x, vert.no.z, -vert.no.y))
                out.write('},\n')
        out.write('};\n\n')
   
    if editmode: Window.EditMode(1)
    out.write('#define k%sNumberOfVertices\t%i\n' % (basename, len(mesh.faces) * 3) )

    out.write('// Drawing Code:\n')
    out.write('// glEnableClientState(GL_VERTEX_ARRAY);\n')
    if (mesh.faceUV):
        out.write('// glEnableClientState(GL_TEXTURE_COORD_ARRAY);\n')
    elif (mesh.vertexColors):
        out.write('// glEnableClientState(GL_COLOR_ARRAY);\n')
        out.write('// glEnable(GL_COLOR_MATERIAL)\n')
    out.write('// glEnableClientState(GL_NORMAL_ARRAY);\n')
    out.write('// glVertexPointer(3, GL_FLOAT, sizeof(')
    if (mesh.faceUV):
        out.write('TexturedVertexData3D')
    elif (mesh.vertexColors):
        out.write('ColoredVertexData3D')
    else:
        out.write('VertexData3D')
    out.write('), &%sVertexData[0].vertex);\n' % basename)
    out.write('// glNormalPointer(GL_FLOAT, sizeof(')
    if (mesh.faceUV):
        out.write('TexturedVertexData3D')
    elif (mesh.vertexColors):
        out.write('ColoredVertexData3D')
    else:
        out.write('VertexData3D')
    out.write('), &%sVertexData[0].normal);\n' % basename)
    if (mesh.faceUV):
        out.write('// glTexCoordPointer(2, GL_FLOAT, sizeof(TexturedVertexData3D), &%sVertexData[0].texCoord);\n' % basename)
    elif (mesh.vertexColors):
        out.write('// glColorPointer(4, GL_FLOAT, sizeof(ColoredVertexData3D), &%sVertexData[0].color);\n' % basename)
    out.write('// glDrawArrays(GL_TRIANGLES, 0, k%sNumberOfVertices);\n' % basename)
    out.write('// glDisableClientState(GL_VERTEX_ARRAY);\n')
    if (mesh.faceUV):
        out.write('// glDisableClientState(GL_TEXTURE_COORD_ARRAY);\n')
    elif (mesh.vertexColors):
        out.write('// glDisableClientState(GL_NORMAL_ARRAY);\n')
        out.write('// glDisable(GL_COLOR_MATERIAL);\n')
    out.write('// glDisableClientState(GL_NORMAL_ARRAY);\n\n\n')
   
    out.close()


filename = os.path.splitext(Blender.Get('filename'))[0]
Blender.Window.FileSelector(write_obj, "Export", '%s.h' % filename)


Но оказалось, что под 2.49 есть скрипт получше если скачать их все отсюда https://wiki.blender.org/index.php/Extensions:2.4/Py/Scripts/Bundles
Scripts->System->OpenGL-Code (.h)
Вдруг, кому-то пригодится...
Вот такой С++ код производит:

Код
/////////////////////////////////////////////////////////////////////////
//
//    00.h - Renderfunctions
//
//    This file was created by the OpenGL-Export-Script for Blender.
//
//    Export-Time: 03.08.2016, 02:21:13
//
//    Script written by Michael Gantenbrinker.
//
/////////////////////////////////////////////////////////////////////////

#ifndef __00_H__
#define __00_H__


/////////////////////////////////////////////////////////////////////////
// DEFINES
#define NUM_MESHES 1
#define NUM_LIGHTS 0


/////////////////////////////////////////////////////////////////////////
// CONSTANTS
// Vertex-Array for each Mesh
const float fVertices_1[8][3] = { {1.000000f, 1.000000f, -1.000000f}, {1.000000f, -1.000000f, -1.000000f}, {-1.000000f, -1.000000f, -1.000000f}, {-1.000000f, 1.000000f, -1.000000f},
{1.000000f, 0.999999f, 1.000000f}, {0.999999f, -1.000001f, 1.000000f}, {-1.000000f, -1.000000f, 1.000000f}, {-1.000000f, 1.000000f, 1.000000f}
 };
// Normal-Array for each Mesh
const float fNormals_1[8][3] = { {0.577349f, 0.577349f, -0.577349f}, {0.577349f, -0.577349f, -0.577349f}, {-0.577349f, -0.577349f, -0.577349f}, {-0.577349f, 0.577349f, -0.577349f},
{0.577349f, 0.577349f, 0.577349f}, {0.577349f, -0.577349f, 0.577349f}, {-0.577349f, -0.577349f, 0.577349f}, {-0.577349f, 0.577349f, 0.577349f}
 };

// Triangle-Indices for each Mesh

// Quad-Indices for each Mesh
const unsigned long ulQuadIndices_1[6][4] = { {0, 1, 2, 3}, {4, 7, 6, 5}, {0, 4, 5, 1}, {1, 5, 6, 2}, {2, 6, 7, 3}, {4, 0, 3, 7} };

// Array with Vertex-Array-Pointers
const float* pVertexPointers[] = {&fVertices_1[0][0]};
// Array with Normal-Array-Pointers
const float* pNormalPointers[] = {&fNormals_1[0][0]};
// Array with TriangleIndex-Array-Pointers
const unsigned long* pTriangleIndexPointers[] = {0};
// Array with QuadIndex-Array-Pointers
const unsigned long* pQuadIndexPointers[] = {&ulQuadIndices_1[0][0]};

// Array with Vertex-Array-Lengths
const unsigned long ulVertexLengths[] = {8};
// Array with TriangleIndex-Array-Lengths
const unsigned long ulTriangleIndexLengths[] = {0};
// Array with QuadIndex-Array-Lengths
const unsigned long ulQuadIndexLengths[] = {6};


void Init()
{
}

void Render(int iWidth = 1024, int iHeight = 768)
{
// Setup Projektion-Matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double dAspectRatio = (double)iWidth / (double)iHeight;
gluPerspective(45.0f, dAspectRatio, 1.0f, 100.0f);
glViewport(0, 0, iWidth, iHeight);
gluLookAt(5.0f, 5.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);

// Setup Lights
float lPos[] = {5.0f, 5.0f, 5.0f, 1.0f};
float lDir[] = {-0.707f, -0.707f, -0.707f};
glLightfv(GL_LIGHT0, GL_AMBIENT,               StdColor_White);
glLightfv(GL_LIGHT0, GL_DIFFUSE,               StdColor_BrightGrey);
glLightfv(GL_LIGHT0, GL_SPECULAR,              StdColor_White);
glLightfv(GL_LIGHT0, GL_POSITION,              lPos);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION,        lDir);
glLightf (GL_LIGHT0, GL_SPOT_CUTOFF,           180.f);
glLightf (GL_LIGHT0, GL_SPOT_EXPONENT,         1.0f);
glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION,  1.0f);
glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION,    0.6f);
glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.06f);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
// Setup Scene-Content
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float*         fVertices = 0;
float*         fNormals = 0;
unsigned long* ulTriangleIndices = 0;
unsigned long* ulQuadIndices = 0;
unsigned long* ulPtr = 0;

for(int i = 0; i < NUM_MESHES; i++)
{
fVertices = (float*)pVertexPointers[i];
fNormals = (float*)pNormalPointers[i];
ulTriangleIndices = (unsigned long*)pTriangleIndexPointers[i];
ulQuadIndices = (unsigned long*)pQuadIndexPointers[i];

if(ulTriangleIndices)
{
glBegin(GL_TRIANGLES);
unsigned long t = 0;
while(t < ulTriangleIndexLengths[i]*3)
{
ulPtr = &ulTriangleIndices[t];
glNormal3fv(&fNormals[ulPtr[0]*3]);
glVertex3fv(&fVertices[ulPtr[0]*3]);

glNormal3fv(&fNormals[ulPtr[1]*3]);
glVertex3fv(&fVertices[ulPtr[1]*3]);

glNormal3fv(&fNormals[ulPtr[2]*3]);
glVertex3fv(&fVertices[ulPtr[2]*3]);

t += 3;
}
glEnd();
}

if(ulQuadIndices)
{
glBegin(GL_QUADS);
unsigned long q = 0;
while(q < ulQuadIndexLengths[i]*4)
{
ulPtr = &ulQuadIndices[q];
glNormal3fv(&fNormals[ulPtr[0]*3]);
glVertex3fv(&fVertices[ulPtr[0]*3]);

glNormal3fv(&fNormals[ulPtr[1]*3]);
glVertex3fv(&fVertices[ulPtr[1]*3]);

glNormal3fv(&fNormals[ulPtr[2]*3]);
glVertex3fv(&fVertices[ulPtr[2]*3]);

glNormal3fv(&fNormals[ulPtr[3]*3]);
glVertex3fv(&fVertices[ulPtr[3]*3]);

q += 4;
}
glEnd();
}
}
}

#endif  /* __00_H__ */

« Последнее редактирование: 03 Август 2016, 02:31:41 от Samovar »

 


Яметрика

* По форуму

* Рекламный блок

* Последние вложения

1 (1).png
Скачано: 3811
Автор: LEXA ANЭGROWND
blender.png
Скачано: 3799
Автор: ipv2007
4.png
Скачано: 3794
Автор: hiroyukiss
2.png
Скачано: 3833
Автор: hiroyukiss

Скачано: 3880
Автор: Dilifa12